* 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
This commit is contained in:
Ingo Weinhold
2009-07-01 22:09:33 +00:00
parent 7aa7cb4b54
commit 3c5dbb462d
28 changed files with 1274 additions and 27 deletions
+11
View File
@@ -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
:
<nogrist>Debugger_demangler.o
<nogrist>Debugger_disasm_x86.o
+1 -1
View File
@@ -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();
+1
View File
@@ -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',
+164 -3
View File
@@ -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<ImageHandler>, 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<ImageHandler>* 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<ImageInfo> 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<LocatableFile> 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,...)
{
+12 -1
View File
@@ -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<ImageHandlerHashDefinition> 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;
@@ -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,
@@ -23,6 +23,7 @@ public:
status_t Init();
virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo,
LocatableFile* imageFile,
SpecificImageDebugInfo*& _imageDebugInfo);
private:
@@ -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)
@@ -21,6 +21,7 @@ public:
status_t Init();
virtual status_t CreateImageDebugInfo(const ImageInfo& imageInfo,
LocatableFile* imageFile,
SpecificImageDebugInfo*& _imageDebugInfo);
private:
@@ -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;
};
@@ -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;
@@ -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:
+1
View File
@@ -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
+541
View File
@@ -0,0 +1,541 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "FileManager.h"
#include <new>
#include <AutoLocker.h>
#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<LocatableEntry>* 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<LocatableDirectory*>(entry);
if (directory == NULL)
return false;
entry->SetLocatedPath(locatedPath, implicit);
} else if (S_ISREG(st.st_mode)) {
LocatableFile* file = dynamic_cast<LocatableFile*>(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<LocatableDirectory*>(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<LocatableFile*>(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<LocatableDirectory*>(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<FileManager> locker(this);
return fTargetDomain->GetFile(directory, name);
}
LocatableFile*
FileManager::GetTargetFile(const BString& path)
{
AutoLocker<FileManager> locker(this);
return fTargetDomain->GetFile(path);
}
void
FileManager::TargetEntryLocated(const BString& path, const BString& locatedPath)
{
AutoLocker<FileManager> locker(this);
fTargetDomain->EntryLocated(path, locatedPath);
}
LocatableFile*
FileManager::GetSourceFile(const BString& directory, const BString& name)
{
AutoLocker<FileManager> locker(this);
return fSourceDomain->GetFile(directory, name);
}
LocatableFile*
FileManager::GetSourceFile(const BString& path)
{
AutoLocker<FileManager> locker(this);
return fSourceDomain->GetFile(path);
}
void
FileManager::SourceEntryLocated(const BString& path, const BString& locatedPath)
{
AutoLocker<FileManager> locker(this);
fSourceDomain->EntryLocated(path, locatedPath);
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef FILE_MANAGER_H
#define FILE_MANAGER_H
#include <Locker.h>
#include <String.h>
#include <util/OpenHashTable.h>
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<EntryHashDefinition> LocatableEntryTable;
private:
BLocker fLock;
Domain* fTargetDomain;
Domain* fSourceDomain;
};
#endif // FILE_MANAGER_H
@@ -0,0 +1,78 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* 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);
}
@@ -0,0 +1,38 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* 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
@@ -0,0 +1,49 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* 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<LocatableEntryOwner> locker(fOwner);
if (CountReferences() == 0 && fOwner->LocatableEntryUnused(this))
delete this;
}
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef LOCATABLE_ENTRY_H
#define LOCATABLE_ENTRY_H
#include <String.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
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<LocatableEntry>,
public HashTableLink<LocatableEntry> {
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<LocatableEntry> LocatableEntryList;
#endif // LOCATABLE_ENTRY_H
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "LocatableFile.h"
#include <AutoLocker.h>
#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<LocatableEntryOwner> 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<LocatableEntryOwner> locker(fOwner);
return fListeners.AddItem(listener);
}
void
LocatableFile::RemoveListener(Listener* listener)
{
AutoLocker<LocatableEntryOwner> 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()
{
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef LOCATABLE_FILE_H
#define LOCATABLE_FILE_H
#include <ObjectList.h>
#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<Listener> 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
+8 -2
View File
@@ -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();
}
+5 -1
View File
@@ -22,12 +22,14 @@ enum image_debug_info_state {
class ImageDebugInfo;
class LocatableFile;
class Team;
class Image : public Referenceable, public DoublyLinkedListLinkImpl<Image> {
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;
+5 -11
View File
@@ -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;
+2 -1
View File
@@ -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);
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected]. 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;
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected]. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
#include <String.h>
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