From 3c5dbb462d2d407e87196e6eb5c24162df9a5af7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 1 Jul 2009 22:09:33 +0000 Subject: [PATCH] * Moved Array.h to new directory "types". * Added StringUtils with string hash functions. * Added Locatable{Entry,File,Directory} and FileManager classes to manage the mapping from debug info/target file names to local file names. * Image does now have a LocatableFile referring to the image's shared object file. Added listening to location changes of these files to TeamDebugger. No action is taken yet (should trigger reloading the debug info). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31368 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debugger/Jamfile | 11 + src/apps/debugger/Jobs.cpp | 2 +- src/apps/debugger/MessageCodes.h | 1 + src/apps/debugger/TeamDebugger.cpp | 167 +++++- src/apps/debugger/TeamDebugger.h | 13 +- .../debug_info/DebuggerTeamDebugInfo.cpp | 2 +- .../debug_info/DebuggerTeamDebugInfo.h | 1 + .../debug_info/DwarfTeamDebugInfo.cpp | 10 +- .../debugger/debug_info/DwarfTeamDebugInfo.h | 1 + .../debug_info/SpecificTeamDebugInfo.h | 2 + .../debugger/debug_info/TeamDebugInfo.cpp | 4 +- src/apps/debugger/debug_info/TeamDebugInfo.h | 2 + src/apps/debugger/dwarf/Jamfile | 1 + src/apps/debugger/files/FileManager.cpp | 541 ++++++++++++++++++ src/apps/debugger/files/FileManager.h | 58 ++ .../debugger/files/LocatableDirectory.cpp | 78 +++ src/apps/debugger/files/LocatableDirectory.h | 38 ++ src/apps/debugger/files/LocatableEntry.cpp | 49 ++ src/apps/debugger/files/LocatableEntry.h | 67 +++ src/apps/debugger/files/LocatableFile.cpp | 111 ++++ src/apps/debugger/files/LocatableFile.h | 56 ++ src/apps/debugger/model/Image.cpp | 10 +- src/apps/debugger/model/Image.h | 6 +- src/apps/debugger/model/Team.cpp | 16 +- src/apps/debugger/model/Team.h | 3 +- src/apps/debugger/{ => util}/Array.h | 0 src/apps/debugger/util/StringUtils.cpp | 26 + src/apps/debugger/util/StringUtils.h | 25 + 28 files changed, 1274 insertions(+), 27 deletions(-) create mode 100644 src/apps/debugger/files/FileManager.cpp create mode 100644 src/apps/debugger/files/FileManager.h create mode 100644 src/apps/debugger/files/LocatableDirectory.cpp create mode 100644 src/apps/debugger/files/LocatableDirectory.h create mode 100644 src/apps/debugger/files/LocatableEntry.cpp create mode 100644 src/apps/debugger/files/LocatableEntry.h create mode 100644 src/apps/debugger/files/LocatableFile.cpp create mode 100644 src/apps/debugger/files/LocatableFile.h rename src/apps/debugger/{ => util}/Array.h (100%) create mode 100644 src/apps/debugger/util/StringUtils.cpp create mode 100644 src/apps/debugger/util/StringUtils.h diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index f77f840674..4994da8cda 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -11,9 +11,11 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch x86 ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ; local debugAnalyzerSources = [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ; @@ -68,6 +70,12 @@ Application Debugger : # elf ElfFile.cpp + # files + FileManager.cpp + LocatableDirectory.cpp + LocatableEntry.cpp + LocatableFile.cpp + # gui/team_window ImageFunctionsView.cpp ImageListView.cpp @@ -96,6 +104,9 @@ Application Debugger : # types TargetAddressRangeList.cpp + # util + StringUtils.cpp + : Debugger_demangler.o Debugger_disasm_x86.o diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 466e2268f3..79b32da855 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -253,7 +253,7 @@ LoadImageDebugInfoJob::Do() // create the debug info ImageDebugInfo* debugInfo; status_t error = fImage->GetTeam()->DebugInfo()->LoadImageDebugInfo( - imageInfo, debugInfo); + imageInfo, fImage->ImageFile(), debugInfo); // set the result locker.Lock(); diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index cbbddc222c..b40b8a5177 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -19,6 +19,7 @@ enum { MSG_THREAD_CPU_STATE_CHANGED = 'tcsc', MSG_THREAD_STACK_TRACE_CHANGED = 'tstc', MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic', + MSG_IMAGE_FILE_CHANGED = 'ifch', MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc', MSG_USER_BREAKPOINT_CHANGED = 'ubrc', MSG_DEBUGGER_EVENT = 'dbge', diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index d16ff5153d..4ce7e9df51 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -20,12 +20,93 @@ #include "BreakpointManager.h" #include "CpuState.h" #include "DebuggerInterface.h" +#include "FileManager.h" #include "Jobs.h" +#include "LocatableFile.h" #include "MessageCodes.h" #include "Statement.h" #include "TeamDebugInfo.h" #include "TeamDebugModel.h" +// #pragma mark - ImageHandler + + +struct TeamDebugger::ImageHandler : public Referenceable, + public HashTableLink, private LocatableFile::Listener { +public: + ImageHandler(TeamDebugger* teamDebugger, Image* image) + : + fTeamDebugger(teamDebugger), + fImage(image) + { + fImage->AcquireReference(); + if (fImage->ImageFile() != NULL) + fImage->ImageFile()->AddListener(this); + } + + ~ImageHandler() + { + if (fImage->ImageFile() != NULL) + fImage->ImageFile()->RemoveListener(this); + fImage->ReleaseReference(); + } + + Image* GetImage() const + { + return fImage; + } + + image_id ImageID() const + { + return fImage->ID(); + } + +private: + // LocatableFile::Listener + virtual void LocatableFileChanged(LocatableFile* file) + { + BMessage message(MSG_IMAGE_FILE_CHANGED); + message.AddInt32("image", fImage->ID()); + fTeamDebugger->PostMessage(&message); + } + +private: + TeamDebugger* fTeamDebugger; + Image* fImage; +}; + + +// #pragma mark - ImageHandlerHashDefinition + + +struct TeamDebugger::ImageHandlerHashDefinition { + typedef image_id KeyType; + typedef ImageHandler ValueType; + + size_t HashKey(image_id key) const + { + return (size_t)key; + } + + size_t Hash(const ImageHandler* value) const + { + return HashKey(value->ImageID()); + } + + bool Compare(image_id key, const ImageHandler* value) const + { + return value->ImageID() == key; + } + + HashTableLink* GetLink(ImageHandler* value) const + { + return value; + } +}; + + +// #pragma mark - TeamDebugger + TeamDebugger::TeamDebugger(Listener* listener) : @@ -34,7 +115,9 @@ TeamDebugger::TeamDebugger(Listener* listener) fTeam(NULL), fDebugModel(NULL), fTeamID(-1), + fImageHandlers(NULL), fDebuggerInterface(NULL), + fFileManager(NULL), fWorker(NULL), fBreakpointManager(NULL), fDebugEventListener(-1), @@ -73,15 +156,25 @@ TeamDebugger::~TeamDebugger() ThreadHandler* threadHandler = fThreadHandlers.Clear(true); while (threadHandler != NULL) { ThreadHandler* next = threadHandler->fNext; - threadHandler->RemoveReference(); + threadHandler->ReleaseReference(); threadHandler = next; } + ImageHandler* imageHandler = fImageHandlers->Clear(true); + while (imageHandler != NULL) { + ImageHandler* next = imageHandler->fNext; + imageHandler->ReleaseReference(); + imageHandler = next; + } + + delete fImageHandlers; + delete fBreakpointManager; delete fDebuggerInterface; delete fWorker; delete fDebugModel; delete fTeam; + delete fFileManager; fListener->TeamDebuggerQuit(this); } @@ -90,6 +183,9 @@ TeamDebugger::~TeamDebugger() status_t TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) { + bool targetIsLocal = true; + // TODO: Support non-local targets! + fTeamID = teamID; // create debugger interface @@ -101,6 +197,15 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) if (error != B_OK) return error; + // create file manager + fFileManager = new(std::nothrow) FileManager; + if (fFileManager == NULL) + return B_NO_MEMORY; + + error = fFileManager->Init(targetIsLocal); + if (error != B_OK) + return error; + // create team debug info TeamDebugInfo* teamDebugInfo = new(std::nothrow) TeamDebugInfo( fDebuggerInterface, fDebuggerInterface->GetArchitecture()); @@ -137,6 +242,15 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) if (error != B_OK) return error; + // create image handler table + fImageHandlers = new(std::nothrow) ImageHandlerTable; + if (fImageHandlers == NULL) + return B_NO_MEMORY; + + error = fImageHandlers->Init(); + if (error != B_OK) + return error; + // create our worker fWorker = new(std::nothrow) Worker; if (fWorker == NULL) @@ -198,7 +312,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) BObjectList imageInfos(20, true); status_t error = fDebuggerInterface->GetImageInfos(imageInfos); for (int32 i = 0; ImageInfo* info = imageInfos.ItemAt(i); i++) { - error = fTeam->AddImage(*info); + error = _AddImage(*info); if (error != B_OK) return error; } @@ -320,6 +434,16 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_IMAGE_FILE_CHANGED: + { + int32 imageID; + if (message->FindInt32("image", &imageID) != B_OK) + break; + + _HandleImageFileChanged(imageID); + break; + } + case MSG_DEBUGGER_EVENT: { DebugEvent* event; @@ -663,7 +787,7 @@ bool TeamDebugger::_HandleImageCreated(ImageCreatedEvent* event) { AutoLocker< ::Team> locker(fTeam); - fTeam->AddImage(event->GetImageInfo()); + _AddImage(event->GetImageInfo()); return false; } @@ -673,10 +797,26 @@ TeamDebugger::_HandleImageDeleted(ImageDeletedEvent* event) { AutoLocker< ::Team> locker(fTeam); fTeam->RemoveImage(event->GetImageInfo().ImageID()); + + ImageHandler* imageHandler = fImageHandlers->Lookup( + event->GetImageInfo().ImageID()); + if (imageHandler != NULL) { + fImageHandlers->Remove(imageHandler); + imageHandler->ReleaseReference(); + } + return false; } +void +TeamDebugger::_HandleImageFileChanged(image_id imageID) +{ +printf("TeamDebugger::_HandleImageFileChanged(%ld)\n", imageID); +// TODO: Reload the debug info! +} + + void TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled) { @@ -710,6 +850,27 @@ TeamDebugger::_GetThreadHandler(thread_id threadID) } +status_t +TeamDebugger::_AddImage(const ImageInfo& imageInfo) +{ + LocatableFile* file = NULL; + if (strchr(imageInfo.Name(), '/') != NULL) + file = fFileManager->GetTargetFile(imageInfo.Name()); + Reference imageFileReference(file, true); + + Image* image; + status_t error = fTeam->AddImage(imageInfo, file, &image); + if (error != B_OK) + return error; + + ImageHandler* imageHandler = new(std::nothrow) ImageHandler(this, image); + if (imageHandler != NULL) + fImageHandlers->Insert(imageHandler); + + return B_OK; +} + + void TeamDebugger::_NotifyUser(const char* title, const char* text,...) { diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index 353be20a8c..926302841f 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -18,6 +18,7 @@ class DebuggerInterface; +class FileManager; class TeamDebugInfo; class TeamDebugModel; @@ -64,6 +65,11 @@ private: virtual void ThreadStackTraceChanged( const ::Team::ThreadEvent& event); +private: + struct ImageHandler; + struct ImageHandlerHashDefinition; + typedef OpenHashTable ImageHandlerTable; + private: static status_t _DebugEventListenerEntry(void* data); status_t _DebugEventListener(); @@ -79,14 +85,17 @@ private: bool _HandleImageDeleted( ImageDeletedEvent* event); + void _HandleImageFileChanged(image_id imageID); + void _HandleSetUserBreakpoint(target_addr_t address, bool enabled); void _HandleClearUserBreakpoint( target_addr_t address); - ThreadHandler* _GetThreadHandler(thread_id threadID); + status_t _AddImage(const ImageInfo& imageInfo); + void _NotifyUser(const char* title, const char* text,...); @@ -97,8 +106,10 @@ private: team_id fTeamID; ThreadHandlerTable fThreadHandlers; // protected by the team lock + ImageHandlerTable* fImageHandlers; DebuggerInterface* fDebuggerInterface; TeamDebugInfo* fTeamDebugInfo; + FileManager* fFileManager; Worker* fWorker; BreakpointManager* fBreakpointManager; thread_id fDebugEventListener; diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp index 40ef0cc1de..3c46e5f5df 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.cpp @@ -33,7 +33,7 @@ DebuggerTeamDebugInfo::Init() status_t DebuggerTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, - SpecificImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo) { DebuggerImageDebugInfo* debuggerInfo = new(std::nothrow) DebuggerImageDebugInfo(imageInfo, diff --git a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h index 41e362cbd9..d3895c0c1e 100644 --- a/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerTeamDebugInfo.h @@ -23,6 +23,7 @@ public: status_t Init(); virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, + LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp index 9371162e3e..9bfb3a6937 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp @@ -11,6 +11,7 @@ #include "DwarfImageDebugInfo.h" #include "DwarfManager.h" +#include "LocatableFile.h" DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture) @@ -44,15 +45,16 @@ DwarfTeamDebugInfo::Init() status_t DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo, - SpecificImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo) { - // We only want images that belong to shared objects. - if (strchr(imageInfo.Name(), '/') == NULL) + // We only like images whose file we can play with. + BString filePath; + if (imageFile == NULL || !imageFile->GetLocatedPath(filePath)) return B_ENTRY_NOT_FOUND; // try to load the DWARF file DwarfFile* file; - status_t error = fManager->LoadFile(imageInfo.Name(), file); + status_t error = fManager->LoadFile(filePath, file); if (error == B_OK) error = fManager->FinishLoading(); if (error != B_OK) diff --git a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h index f2e7a3defb..9e21119f1c 100644 --- a/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfTeamDebugInfo.h @@ -21,6 +21,7 @@ public: status_t Init(); virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, + LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h index 59f2755e93..1d3a47d103 100644 --- a/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificTeamDebugInfo.h @@ -9,6 +9,7 @@ class ImageInfo; +class LocatableFile; class SpecificImageDebugInfo; @@ -17,6 +18,7 @@ public: virtual ~SpecificTeamDebugInfo(); virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo, + LocatableFile* imageFile, SpecificImageDebugInfo*& _imageDebugInfo) = 0; }; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index 2613b132a2..3c04965004 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -67,7 +67,7 @@ TeamDebugInfo::Init() status_t TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, - ImageDebugInfo*& _imageDebugInfo) + LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo) { ImageDebugInfo* imageDebugInfo = new(std::nothrow) ImageDebugInfo( imageInfo); @@ -79,7 +79,7 @@ TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, = fSpecificInfos.ItemAt(i); i++) { SpecificImageDebugInfo* specificImageInfo; status_t error = specificTeamInfo->CreateImageDebugInfo(imageInfo, - specificImageInfo); + imageFile, specificImageInfo); if (error == B_OK) { if (!imageDebugInfo->AddSpecificInfo(specificImageInfo)) { delete specificImageInfo; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index bdc3e28803..72e089e4e1 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -15,6 +15,7 @@ class Architecture; class DebuggerInterface; class ImageDebugInfo; class ImageInfo; +class LocatableFile; class SpecificTeamDebugInfo; @@ -28,6 +29,7 @@ public: status_t Init(); status_t LoadImageDebugInfo(const ImageInfo& imageInfo, + LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo); private: diff --git a/src/apps/debugger/dwarf/Jamfile b/src/apps/debugger/dwarf/Jamfile index 47f82f4491..7cc3444a76 100644 --- a/src/apps/debugger/dwarf/Jamfile +++ b/src/apps/debugger/dwarf/Jamfile @@ -9,6 +9,7 @@ UsePrivateSystemHeaders ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) elf ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) types ] ; +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) util ] ; MergeObject Debugger_dwarf.o diff --git a/src/apps/debugger/files/FileManager.cpp b/src/apps/debugger/files/FileManager.cpp new file mode 100644 index 0000000000..07caa80760 --- /dev/null +++ b/src/apps/debugger/files/FileManager.cpp @@ -0,0 +1,541 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "FileManager.h" + +#include + +#include + +#include "LocatableDirectory.h" +#include "LocatableFile.h" +#include "StringUtils.h" + + +// #pragma mark - EntryPath + + +struct FileManager::EntryPath { + const char* directory; + const char* name; + + EntryPath(const char* directory, const char* name) + : + directory(directory), + name(name) + { + } + + EntryPath(const BString& directory, const BString& name) + : + directory(directory.Length() > 0 ? directory.String() : NULL), + name(name.String()) + { + } + + EntryPath(const LocatableEntry* entry) + : + directory(entry->Parent() != NULL ? entry->Parent()->Path() : NULL), + name(entry->Name()) + { + } + + EntryPath(const EntryPath& other) + : + directory(other.directory), + name(other.name) + { + } + + size_t HashValue() const + { + return StringUtils::HashValue(directory) + ^ StringUtils::HashValue(name); + } + + bool operator==(const EntryPath& other) const + { + if (directory != other.directory + && (directory == NULL || other.directory == NULL + || strcmp(directory, other.directory) != 0)) { + return false; + } + + return strcmp(name, other.name) == 0; + } +}; + + +// #pragma mark - EntryHashDefinition + + +struct FileManager::EntryHashDefinition { + typedef EntryPath KeyType; + typedef LocatableEntry ValueType; + + size_t HashKey(const EntryPath& key) const + { + return key.HashValue(); + } + + size_t Hash(const LocatableEntry* value) const + { + return HashKey(EntryPath(value)); + } + + bool Compare(const EntryPath& key, const LocatableEntry* value) const + { + return EntryPath(value) == key; + } + + HashTableLink* GetLink(LocatableEntry* value) const + { + return value; + } +}; + + +// #pragma mark - Domain + + +class FileManager::Domain : private LocatableEntryOwner { +public: + Domain(FileManager* manager, bool isLocal) + : + fManager(manager), + fIsLocal(isLocal) + { + } + + ~Domain() + { + LocatableEntry* entry = fEntries.Clear(true); + while (entry != NULL) { + LocatableEntry* next = entry->fNext; + entry->RemoveReference(); + entry = next; + } + } + + status_t Init() + { + status_t error = fEntries.Init(); + if (error != B_OK) + return error; + + return B_OK; + } + + LocatableFile* GetFile(const BString& directoryPath, const BString& name) + { + BString normalizedDirectoryPath; + _NormalizePath(directoryPath, normalizedDirectoryPath); + LocatableFile* file = _GetFile(normalizedDirectoryPath, name); + if (file == NULL) + return NULL; + + // try to auto-locate the file + if (LocatableDirectory* directory = file->Parent()) { + if (directory->State() == LOCATABLE_ENTRY_UNLOCATED) { + // parent not yet located -- try locate with the entry's path + BString path; + file->GetPath(path); + _LocateEntry(file, path, true, true); + } else { + // parent already located -- locate the entry in the parent + BString locatedDirectoryPath; + if (directory->GetLocatedPath(locatedDirectoryPath)) + _LocateEntryInParentDir(file, locatedDirectoryPath); + } + } + + return file; + } + + LocatableFile* GetFile(const BString& path) + { + BString directoryPath; + BString name; + _SplitPath(path, directoryPath, name); + return _GetFile(directoryPath, name); + } + + void EntryLocated(const BString& path, const BString& locatedPath) + { + BString directory; + BString name; + _SplitPath(path, directory, name); + + LocatableEntry* entry = fEntries.Lookup(EntryPath(directory, name)); + if (entry == NULL) + return; + + _LocateEntry(entry, locatedPath, false, true); + } + +private: + virtual bool Lock() + { + return fManager->Lock(); + } + + virtual void Unlock() + { + fManager->Unlock(); + } + + virtual bool LocatableEntryUnused(LocatableEntry* entry) + { + fEntries.Remove(entry); + return true; + } + + bool _LocateDirectory(LocatableDirectory* directory, + const BString& locatedPath) + { + if (directory == NULL + || directory->State() != LOCATABLE_ENTRY_UNLOCATED) { + return false; + } + + // locate the parent, if possible, otherwise this directory + BString locatedDirectory; + BString locatedName; + _SplitNormalizedPath(locatedPath, locatedDirectory, locatedName); + if (locatedName != directory->Name() + || !_LocateDirectory(directory->Parent(), locatedDirectory)) { + directory->SetLocatedPath(locatedPath, true); + _LocateEntries(directory, locatedPath); + } + + return true; + } + + bool _LocateEntry(LocatableEntry* entry, const BString& locatedPath, + bool implicit, bool locateAncestors) + { + if (implicit && entry->State() == LOCATABLE_ENTRY_LOCATED_EXPLICITLY) + return false; + + struct stat st; + if (stat(locatedPath, &st) != 0) + return false; + + if (S_ISDIR(st.st_mode)) { + LocatableDirectory* directory + = dynamic_cast(entry); + if (directory == NULL) + return false; + entry->SetLocatedPath(locatedPath, implicit); + } else if (S_ISREG(st.st_mode)) { + LocatableFile* file = dynamic_cast(entry); + if (file == NULL) + return false; + entry->SetLocatedPath(locatedPath, implicit); + } + + // locate the ancestor directories, if requested + if (locateAncestors) { + BString locatedDirectory; + BString locatedName; + _SplitPath(locatedPath, locatedDirectory, locatedName); + if (locatedName == entry->Name()) + _LocateDirectory(entry->Parent(), locatedDirectory); + } + + return true; + } + + bool _LocateEntryInParentDir(LocatableEntry* entry, + const BString& locatedDirectoryPath) + { + // construct the located entry path + BString locatedEntryPath(locatedDirectoryPath); + int32 pathLength = locatedEntryPath.Length(); + if (pathLength >= 1 && locatedEntryPath.ByteAt(pathLength - 1) != '/') + locatedEntryPath << '/'; + locatedEntryPath << entry->Name(); + + return _LocateEntry(entry, locatedEntryPath, true, false); + } + + void _LocateEntries(LocatableDirectory* directory, + const BString& locatedPath) + { + for (LocatableEntryList::ConstIterator it + = directory->Entries().GetIterator(); + LocatableEntry* entry = it.Next();) { + if (entry->State() == LOCATABLE_ENTRY_LOCATED_EXPLICITLY) + continue; + + if (_LocateEntryInParentDir(entry, locatedPath)) { + // recurse for directories + if (LocatableDirectory* subDir + = dynamic_cast(entry)) { + BString locatedEntryPath; + if (subDir->GetLocatedPath(locatedEntryPath)) + _LocateEntries(subDir, locatedEntryPath); + } + } + } + } + + LocatableFile* _GetFile(const BString& directoryPath, const BString& name) + { + // if already know return the file + LocatableEntry* entry = fEntries.Lookup(EntryPath(directoryPath, name)); + if (entry != NULL) { + LocatableFile* file = dynamic_cast(entry); + if (file == NULL) + return NULL; + + file->AcquireReference(); + return file; + } + + // no such file yet -- create it + BString normalizedDirPath; + _NormalizePath(directoryPath, normalizedDirPath); + LocatableDirectory* directory = _GetDirectory(normalizedDirPath); + if (directory == NULL) + return NULL; + + LocatableFile* file = new(std::nothrow) LocatableFile(this, directory, + name); + if (file == NULL) { + directory->ReleaseReference(); + return NULL; + } + + fEntries.Insert(file); + return file; + } + + LocatableDirectory* _GetDirectory(const BString& path) + { + BString directoryPath; + BString fileName; + _SplitNormalizedPath(path, directoryPath, fileName); + + // if already know return the directory + LocatableEntry* entry + = fEntries.Lookup(EntryPath(directoryPath, fileName)); + if (entry != NULL) { + LocatableDirectory* directory + = dynamic_cast(entry); + if (directory == NULL) + return NULL; + directory->AcquireReference(); + return directory; + } + + // get the parent directory + LocatableDirectory* parentDirectory = NULL; + if (directoryPath.Length() > 0) { + parentDirectory = _GetDirectory(directoryPath); + if (parentDirectory == NULL) + return NULL; + } + + // create a new directory + LocatableDirectory* directory = new(std::nothrow) LocatableDirectory( + this, parentDirectory, path); + if (directory == NULL) { + parentDirectory->ReleaseReference(); + return NULL; + } + + // auto-locate, if possible + if (fIsLocal) { + BString dirPath; + directory->GetPath(dirPath); + directory->SetLocatedPath(dirPath, false); + } else if (parentDirectory != NULL + && parentDirectory->State() != LOCATABLE_ENTRY_UNLOCATED) { +// TODO:... + } + + fEntries.Insert(directory); + return directory; + } + + void _NormalizePath(const BString& path, BString& _normalizedPath) + { + BString normalizedPath; + char* buffer = normalizedPath.LockBuffer(path.Length()); + int32 outIndex = 0; + const char* remaining = path.String(); + + while (*remaining != '\0') { + // collapse repeated slashes + if (*remaining == '/') { + buffer[outIndex++] = '/'; + remaining++; + while (*remaining == '/') + remaining++; + } + + if (*remaining == '\0') { + // remove trailing slash (unless it's "/" only) + if (outIndex > 1) + outIndex--; + break; + } + + // skip "." components + if (*remaining == '.') { + if (remaining[1] == '\0') + break; + + if (remaining[1] == '/') { + remaining += 2; + while (*remaining == '/') + remaining++; + continue; + } + } + + // copy path component + while (*remaining != '\0' && *remaining != '/') + buffer[outIndex++] = *(remaining++); + } + + // If the path didn't change, use the original path (BString's copy on + // write mechanism) rather than the new string. + if (outIndex == path.Length()) { + _normalizedPath = path; + } else { + normalizedPath.UnlockBuffer(outIndex); + _normalizedPath = normalizedPath; + } + } + + void _SplitPath(const BString& path, BString& _directory, BString& _name) + { + BString normalized; + _NormalizePath(path, normalized); + _SplitNormalizedPath(normalized, _directory, _name); + } + + void _SplitNormalizedPath(const BString& path, BString& _directory, + BString& _name) + { + // handle single component (including root dir) cases + int32 lastSlash = path.FindLast('/'); + if (lastSlash < 0 || path.Length() == 1) { + _directory = (const char*)NULL; + _name = path; + return; + } + + // handle root dir + one component and multi component cases + if (lastSlash == 0) + _directory = "/"; + else + _directory.SetTo(path, lastSlash); + _name = path.String() + (lastSlash + 1); + } + +private: + FileManager* fManager; + LocatableEntryTable fEntries; + bool fIsLocal; +}; + + +// #pragma mark - FileManager + + +FileManager::FileManager() + : + fLock("file manager"), + fTargetDomain(NULL), + fSourceDomain(NULL) +{ +} + + +FileManager::~FileManager() +{ + delete fTargetDomain; + delete fSourceDomain; +} + + +status_t +FileManager::Init(bool targetIsLocal) +{ + status_t error = fLock.InitCheck(); + if (error != B_OK) + return error; + + // create target domain + fTargetDomain = new(std::nothrow) Domain(this, targetIsLocal); + if (fTargetDomain == NULL) + return B_NO_MEMORY; + + error = fTargetDomain->Init(); + if (error != B_OK) + return error; + + // create source domain + fSourceDomain = new(std::nothrow) Domain(this, false); + if (fSourceDomain == NULL) + return B_NO_MEMORY; + + error = fSourceDomain->Init(); + if (error != B_OK) + return error; + + return B_OK; +} + + +LocatableFile* +FileManager::GetTargetFile(const BString& directory, const BString& name) +{ + AutoLocker locker(this); + return fTargetDomain->GetFile(directory, name); +} + + +LocatableFile* +FileManager::GetTargetFile(const BString& path) +{ + AutoLocker locker(this); + return fTargetDomain->GetFile(path); +} + + +void +FileManager::TargetEntryLocated(const BString& path, const BString& locatedPath) +{ + AutoLocker locker(this); + fTargetDomain->EntryLocated(path, locatedPath); +} + + +LocatableFile* +FileManager::GetSourceFile(const BString& directory, const BString& name) +{ + AutoLocker locker(this); + return fSourceDomain->GetFile(directory, name); +} + + +LocatableFile* +FileManager::GetSourceFile(const BString& path) +{ + AutoLocker locker(this); + return fSourceDomain->GetFile(path); +} + + +void +FileManager::SourceEntryLocated(const BString& path, const BString& locatedPath) +{ + AutoLocker locker(this); + fSourceDomain->EntryLocated(path, locatedPath); +} diff --git a/src/apps/debugger/files/FileManager.h b/src/apps/debugger/files/FileManager.h new file mode 100644 index 0000000000..5c329b2392 --- /dev/null +++ b/src/apps/debugger/files/FileManager.h @@ -0,0 +1,58 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef FILE_MANAGER_H +#define FILE_MANAGER_H + +#include +#include + +#include + + +class LocatableFile; + + +class FileManager { +public: + FileManager(); + ~FileManager(); + + status_t Init(bool targetIsLocal); + + bool Lock() { return fLock.Lock(); } + void Unlock() { fLock.Unlock(); } + + LocatableFile* GetTargetFile(const BString& directory, + const BString& name); + // returns a reference + LocatableFile* GetTargetFile(const BString& path); + // returns a reference + void TargetEntryLocated(const BString& path, + const BString& locatedPath); + + LocatableFile* GetSourceFile(const BString& directory, + const BString& name); + // returns a reference + LocatableFile* GetSourceFile(const BString& path); + // returns a reference + void SourceEntryLocated(const BString& path, + const BString& locatedPath); + +private: + struct EntryPath; + struct EntryHashDefinition; + class Domain; + + typedef OpenHashTable LocatableEntryTable; + +private: + BLocker fLock; + Domain* fTargetDomain; + Domain* fSourceDomain; +}; + + + +#endif // FILE_MANAGER_H diff --git a/src/apps/debugger/files/LocatableDirectory.cpp b/src/apps/debugger/files/LocatableDirectory.cpp new file mode 100644 index 0000000000..e149da73c6 --- /dev/null +++ b/src/apps/debugger/files/LocatableDirectory.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "LocatableDirectory.h" + + +LocatableDirectory::LocatableDirectory(LocatableEntryOwner* owner, + LocatableDirectory* parent, const BString& path) + : + LocatableEntry(owner, parent), + fPath(path), + fLocatedPath() +{ +} + + +LocatableDirectory::~LocatableDirectory() +{ +} + + +const char* +LocatableDirectory::Name() const +{ + int32 lastSlash = fPath.FindLast('/'); + // return -1, if not found + return fPath.String() + (lastSlash + 1); +} + + +const char* +LocatableDirectory::Path() const +{ + return fPath.String(); +} + + +void +LocatableDirectory::GetPath(BString& _path) const +{ + _path = fPath; +} + + +bool +LocatableDirectory::GetLocatedPath(BString& _path) const +{ + if (fLocatedPath.Length() == 0) + return false; + _path = fLocatedPath; + return true; +} + + +void +LocatableDirectory::SetLocatedPath(const BString& path, bool implicit) +{ + fLocatedPath = path; + fState = implicit + ? LOCATABLE_ENTRY_LOCATED_IMPLICITLY + : LOCATABLE_ENTRY_LOCATED_EXPLICITLY; +} + + +void +LocatableDirectory::AddEntry(LocatableEntry* entry) +{ + fEntries.Add(entry); +} + + +void +LocatableDirectory::RemoveEntry(LocatableEntry* entry) +{ + fEntries.Remove(entry); +} diff --git a/src/apps/debugger/files/LocatableDirectory.h b/src/apps/debugger/files/LocatableDirectory.h new file mode 100644 index 0000000000..02e2d2295e --- /dev/null +++ b/src/apps/debugger/files/LocatableDirectory.h @@ -0,0 +1,38 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef LOCATABLE_DIRECTORY_H +#define LOCATABLE_DIRECTORY_H + +#include "LocatableEntry.h" + + +class LocatableDirectory : public LocatableEntry { +public: + LocatableDirectory(LocatableEntryOwner* owner, + LocatableDirectory* parent, + const BString& path); + ~LocatableDirectory(); + + virtual const char* Name() const; + const char* Path() const; + void GetPath(BString& _path) const; + + // mutable (requires locking) + virtual bool GetLocatedPath(BString& _path) const; + virtual void SetLocatedPath(const BString& path, + bool implicit); + + void AddEntry(LocatableEntry* entry); + void RemoveEntry(LocatableEntry* entry); + const LocatableEntryList& Entries() const { return fEntries; } + +private: + BString fPath; + BString fLocatedPath; + LocatableEntryList fEntries; +}; + + +#endif // LOCATABLE_DIRECTORY_H diff --git a/src/apps/debugger/files/LocatableEntry.cpp b/src/apps/debugger/files/LocatableEntry.cpp new file mode 100644 index 0000000000..d2f62e71fb --- /dev/null +++ b/src/apps/debugger/files/LocatableEntry.cpp @@ -0,0 +1,49 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "LocatableEntry.h" + +#include "AutoLocker.h" + +#include "LocatableDirectory.h" + + +// #pragma mark - LocatableEntryOwner + + +LocatableEntryOwner::~LocatableEntryOwner() +{ +} + + +// #pragma mark - LocatableEntry + + +LocatableEntry::LocatableEntry(LocatableEntryOwner* owner, + LocatableDirectory* parent) + : + fOwner(owner), + fParent(parent), + fState(LOCATABLE_ENTRY_UNLOCATED) +{ + if (fParent != NULL) + fParent->AcquireReference(); +} + + +LocatableEntry::~LocatableEntry() +{ + if (fParent != NULL) + fParent->ReleaseReference(); +} + + +void +LocatableEntry::LastReferenceReleased() +{ + AutoLocker locker(fOwner); + if (CountReferences() == 0 && fOwner->LocatableEntryUnused(this)) + delete this; +} diff --git a/src/apps/debugger/files/LocatableEntry.h b/src/apps/debugger/files/LocatableEntry.h new file mode 100644 index 0000000000..2e8f4be4fc --- /dev/null +++ b/src/apps/debugger/files/LocatableEntry.h @@ -0,0 +1,67 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef LOCATABLE_ENTRY_H +#define LOCATABLE_ENTRY_H + +#include + +#include +#include +#include + + +enum locatable_entry_state { + LOCATABLE_ENTRY_UNLOCATED, + LOCATABLE_ENTRY_LOCATED_IMPLICITLY, + LOCATABLE_ENTRY_LOCATED_EXPLICITLY +}; + + +class LocatableDirectory; +class LocatableEntry; + + +class LocatableEntryOwner { +public: + virtual ~LocatableEntryOwner(); + + virtual bool Lock() = 0; + virtual void Unlock() = 0; + + virtual bool LocatableEntryUnused(LocatableEntry* entry) = 0; +}; + + +class LocatableEntry : public Referenceable, + public DoublyLinkedListLinkImpl, + public HashTableLink { +public: + LocatableEntry(LocatableEntryOwner* owner, + LocatableDirectory* parent); + ~LocatableEntry(); + + LocatableDirectory* Parent() const { return fParent; } + virtual const char* Name() const = 0; + + // mutable (requires locking) + locatable_entry_state State() const { return fState; } + virtual bool GetLocatedPath(BString& _path) const = 0; + virtual void SetLocatedPath(const BString& path, + bool implicit) = 0; + +protected: + virtual void LastReferenceReleased(); + +protected: + LocatableEntryOwner* fOwner; + LocatableDirectory* fParent; + locatable_entry_state fState; +}; + + +typedef DoublyLinkedList LocatableEntryList; + + +#endif // LOCATABLE_ENTRY_H diff --git a/src/apps/debugger/files/LocatableFile.cpp b/src/apps/debugger/files/LocatableFile.cpp new file mode 100644 index 0000000000..38ebdc56e0 --- /dev/null +++ b/src/apps/debugger/files/LocatableFile.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "LocatableFile.h" + +#include + +#include "LocatableDirectory.h" + + +// #pragma mark - LocatableFile + + +LocatableFile::LocatableFile(LocatableEntryOwner* owner, + LocatableDirectory* directory, const BString& name) + : + LocatableEntry(owner, directory), + fName(name), + fLocatedPath(), + fListeners(8) +{ +} + + +LocatableFile::~LocatableFile() +{ +} + + +const char* +LocatableFile::Name() const +{ + return fName.String(); +} + + +void +LocatableFile::GetPath(BString& _path) const +{ + fParent->GetPath(_path); + _path << '/' << fName; +} + + +bool +LocatableFile::GetLocatedPath(BString& _path) const +{ + AutoLocker locker(fOwner); + + if (fLocatedPath.Length() > 0) { + _path = fLocatedPath; + return true; + } + + if (!fParent->GetLocatedPath(_path)) + return false; + + _path << '/' << fName; + return true; +} + + +void +LocatableFile::SetLocatedPath(const BString& path, bool implicit) +{ + // called with owner already locked + + if (implicit) { + fLocatedPath = (const char*)NULL; + fState = LOCATABLE_ENTRY_LOCATED_IMPLICITLY; + } else { + fLocatedPath = path; + fState = LOCATABLE_ENTRY_LOCATED_EXPLICITLY; + } + + _NotifyListeners(); +} + + +bool +LocatableFile::AddListener(Listener* listener) +{ + AutoLocker locker(fOwner); + return fListeners.AddItem(listener); +} + + +void +LocatableFile::RemoveListener(Listener* listener) +{ + AutoLocker locker(fOwner); + fListeners.RemoveItem(listener); +} + + +void +LocatableFile::_NotifyListeners() +{ + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) + fListeners.ItemAt(i)->LocatableFileChanged(this); +} + + +// #pragma mark - Listener + + +LocatableFile::Listener::~Listener() +{ +} diff --git a/src/apps/debugger/files/LocatableFile.h b/src/apps/debugger/files/LocatableFile.h new file mode 100644 index 0000000000..8e4777e62a --- /dev/null +++ b/src/apps/debugger/files/LocatableFile.h @@ -0,0 +1,56 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef LOCATABLE_FILE_H +#define LOCATABLE_FILE_H + +#include + +#include "LocatableEntry.h" + + +class LocatableFile : public LocatableEntry { +public: + class Listener; + +public: + LocatableFile(LocatableEntryOwner* owner, + LocatableDirectory* directory, + const BString& name); + ~LocatableFile(); + + virtual const char* Name() const; + void GetPath(BString& _path) const; + + // mutable (requires/does locking) + virtual bool GetLocatedPath(BString& _path) const; + virtual void SetLocatedPath(const BString& path, + bool implicit); + + bool AddListener(Listener* listener); + void RemoveListener(Listener* listener); + +private: + typedef BObjectList ListenerList; + +private: + void _NotifyListeners(); + +private: + BString fName; + BString fLocatedPath; + ListenerList fListeners; +}; + + +class LocatableFile::Listener { +public: + virtual ~Listener(); + + virtual void LocatableFileChanged(LocatableFile* file) = 0; + // called with lock held +}; + + +#endif // LOCATABLE_FILE_H diff --git a/src/apps/debugger/model/Image.cpp b/src/apps/debugger/model/Image.cpp index 3ad42ba7e5..3a081fcee3 100644 --- a/src/apps/debugger/model/Image.cpp +++ b/src/apps/debugger/model/Image.cpp @@ -6,23 +6,29 @@ #include "Image.h" #include "ImageDebugInfo.h" +#include "LocatableFile.h" #include "Team.h" -Image::Image(Team* team,const ImageInfo& imageInfo) +Image::Image(Team* team,const ImageInfo& imageInfo, LocatableFile* imageFile) : fTeam(team), fInfo(imageInfo), + fImageFile(imageFile), fDebugInfo(NULL), fDebugInfoState(IMAGE_DEBUG_INFO_NOT_LOADED) { + if (fImageFile != NULL) + fImageFile->AcquireReference(); } Image::~Image() { if (fDebugInfo != NULL) - fDebugInfo->RemoveReference(); + fDebugInfo->ReleaseReference(); + if (fImageFile != NULL) + fImageFile->ReleaseReference(); } diff --git a/src/apps/debugger/model/Image.h b/src/apps/debugger/model/Image.h index 286789be14..10e22934e6 100644 --- a/src/apps/debugger/model/Image.h +++ b/src/apps/debugger/model/Image.h @@ -22,12 +22,14 @@ enum image_debug_info_state { class ImageDebugInfo; +class LocatableFile; class Team; class Image : public Referenceable, public DoublyLinkedListLinkImpl { public: - Image(Team* team, const ImageInfo& imageInfo); + Image(Team* team, const ImageInfo& imageInfo, + LocatableFile* imageFile); ~Image(); status_t Init(); @@ -37,6 +39,7 @@ public: image_id ID() const { return fInfo.ImageID(); } const char* Name() const { return fInfo.Name(); } const ImageInfo& Info() const { return fInfo; } + LocatableFile* ImageFile() const { return fImageFile; } bool ContainsAddress(target_addr_t address) const; @@ -50,6 +53,7 @@ public: private: Team* fTeam; ImageInfo fInfo; + LocatableFile* fImageFile; // mutable ImageDebugInfo* fDebugInfo; image_debug_info_state fDebugInfoState; diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index dc519d869e..a2428a0a97 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -123,18 +123,11 @@ Team::Threads() const } -void -Team::AddImage(Image* image) -{ - fImages.Add(image); - _NotifyImageAdded(image); -} - - status_t -Team::AddImage(const ImageInfo& imageInfo, Image** _image) +Team::AddImage(const ImageInfo& imageInfo, LocatableFile* imageFile, + Image** _image) { - Image* image = new(std::nothrow) Image(this, imageInfo); + Image* image = new(std::nothrow) Image(this, imageInfo, imageFile); if (image == NULL) return B_NO_MEMORY; @@ -144,7 +137,8 @@ Team::AddImage(const ImageInfo& imageInfo, Image** _image) return error; } - AddImage(image); + fImages.Add(image); + _NotifyImageAdded(image); if (_image != NULL) *_image = image; diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 5cc1736552..fee2c15182 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -28,6 +28,7 @@ enum { }; +class LocatableFile; class TeamDebugInfo; @@ -58,8 +59,8 @@ public: Thread* ThreadByID(thread_id threadID) const; const ThreadList& Threads() const; - void AddImage(Image* image); status_t AddImage(const ImageInfo& imageInfo, + LocatableFile* imageFile, Image** _image = NULL); void RemoveImage(Image* image); bool RemoveImage(image_id imageID); diff --git a/src/apps/debugger/Array.h b/src/apps/debugger/util/Array.h similarity index 100% rename from src/apps/debugger/Array.h rename to src/apps/debugger/util/Array.h diff --git a/src/apps/debugger/util/StringUtils.cpp b/src/apps/debugger/util/StringUtils.cpp new file mode 100644 index 0000000000..7e1eb47d2b --- /dev/null +++ b/src/apps/debugger/util/StringUtils.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ + +#include "StringUtils.h" + + +// from the Dragon Book: a slightly modified hashpjw() +/*static*/ uint32 +StringUtils::HashValue(const char* string) +{ + if (string == NULL) + return 0; + + uint32 h = 0; + + for (; *string; string++) { + uint32 g = h & 0xf0000000; + if (g) + h ^= g >> 24; + h = (h << 4) + *string; + } + + return h; +} diff --git a/src/apps/debugger/util/StringUtils.h b/src/apps/debugger/util/StringUtils.h new file mode 100644 index 0000000000..e2aaca7595 --- /dev/null +++ b/src/apps/debugger/util/StringUtils.h @@ -0,0 +1,25 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef STRING_UTILS_H +#define STRING_UTILS_H + +#include + + +class StringUtils { +public: + static uint32 HashValue(const char* string); + static uint32 HashValue(const BString& string); +}; + + +/*static*/ inline uint32 +StringUtils::HashValue(const BString& string) +{ + return HashValue(string.String()); +} + + +#endif // STRING_UTILS_H