diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 7b03f9d855..4efa15a30b 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -12,6 +12,8 @@ #include "Architecture.h" #include "CpuState.h" #include "DebuggerInterface.h" +#include "DisassembledCode.h" +#include "FileSourceCode.h" #include "Function.h" #include "Image.h" #include "ImageDebugInfo.h" @@ -319,61 +321,73 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, LoadSourceCodeJob::LoadSourceCodeJob( DebuggerInterface* debuggerInterface, Architecture* architecture, - Team* team, Function* function) + Team* team, FunctionInstance* functionInstance, bool loadForFunction) : fDebuggerInterface(debuggerInterface), fArchitecture(architecture), fTeam(team), - fFunction(function) + fFunctionInstance(functionInstance), + fLoadForFunction(loadForFunction) { - fFunction->AddReference(); + fFunctionInstance->AddReference(); } LoadSourceCodeJob::~LoadSourceCodeJob() { - fFunction->RemoveReference(); + fFunctionInstance->RemoveReference(); } JobKey LoadSourceCodeJob::Key() const { - return JobKey(fFunction, JOB_TYPE_LOAD_SOURCE_CODE); + return JobKey(fFunctionInstance, JOB_TYPE_LOAD_SOURCE_CODE); } status_t LoadSourceCodeJob::Do() { - // Get the function debug info for an instance which we can use to load the - // source code. + // if requested, try loading the source code for the function + Function* function = fFunctionInstance->GetFunction(); + if (fLoadForFunction) { + FileSourceCode* sourceCode; + status_t error = fTeam->DebugInfo()->LoadSourceCode( + function->SourceFile(), sourceCode); + + AutoLocker locker(fTeam); + + if (error == B_OK) { + function->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); + sourceCode->RemoveReference(); + return B_OK; + } + + function->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); + } + + // Only try to load the function instance code, if it's not overridden yet. AutoLocker locker(fTeam); - - status_t error = B_OK; - FunctionDebugInfo* functionDebugInfo = NULL; - if (FunctionInstance* instance = fFunction->FirstInstance()) { - functionDebugInfo = instance->GetFunctionDebugInfo(); - } else - error = B_ENTRY_NOT_FOUND; - Reference functionDebugInfoReference(functionDebugInfo); - + if (fFunctionInstance->SourceCodeState() != FUNCTION_SOURCE_LOADING) + return B_OK; locker.Unlock(); - // load the source code, if we can - SourceCode* sourceCode = NULL; - if (error == B_OK) { - error = functionDebugInfo->GetSpecificImageDebugInfo()->LoadSourceCode( - functionDebugInfo, sourceCode); - } + // disassemble the function + DisassembledCode* sourceCode = NULL; + status_t error = fTeam->DebugInfo()->DisassembleFunction(fFunctionInstance, + sourceCode); // set the result locker.Lock(); if (error == B_OK) { - fFunction->SetSourceCode(sourceCode, FUNCTION_SOURCE_LOADED); - sourceCode->RemoveReference(); + if (fFunctionInstance->SourceCodeState() == FUNCTION_SOURCE_LOADING) { + fFunctionInstance->SetSourceCode(sourceCode, + FUNCTION_SOURCE_LOADED); + sourceCode->RemoveReference(); + } } else - fFunction->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); + fFunctionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_UNAVAILABLE); return error; } diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/Jobs.h index b678fc9156..c218c79dce 100644 --- a/src/apps/debugger/Jobs.h +++ b/src/apps/debugger/Jobs.h @@ -13,6 +13,7 @@ class Architecture; class CpuState; class DebuggerInterface; class Function; +class FunctionInstance; class Image; class StackFrame; class Team; @@ -113,7 +114,8 @@ public: LoadSourceCodeJob( DebuggerInterface* debuggerInterface, Architecture* architecture, Team* team, - Function* function); + FunctionInstance* functionInstance, + bool loadForFunction); virtual ~LoadSourceCodeJob(); virtual JobKey Key() const; @@ -123,7 +125,8 @@ private: DebuggerInterface* fDebuggerInterface; Architecture* fArchitecture; Team* fTeam; - Function* fFunction; + FunctionInstance* fFunctionInstance; + bool fLoadForFunction; }; diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index 5c253397cc..2121b5123c 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -489,15 +489,27 @@ TeamDebugger::FunctionSourceCodeRequested(TeamWindow* window, // mark loading AutoLocker< ::Team> locker(fTeam); - if (function->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED) + + if (functionInstance->SourceCodeState() != FUNCTION_SOURCE_NOT_LOADED) return; - function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING); + if (function->SourceCodeState() == FUNCTION_SOURCE_LOADED) + return; + + functionInstance->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING); + + bool loadForFunction = false; + if (function->SourceCodeState() == FUNCTION_SOURCE_NOT_LOADED) { + loadForFunction = true; + function->SetSourceCode(NULL, FUNCTION_SOURCE_LOADING); + } + locker.Unlock(); // schedule the job if (fWorker->ScheduleJob( new(std::nothrow) LoadSourceCodeJob(fDebuggerInterface, - fDebuggerInterface->GetArchitecture(), fTeam, function), + fDebuggerInterface->GetArchitecture(), fTeam, functionInstance, + loadForFunction), this) != B_OK) { // scheduling failed -- mark unavailable locker.Lock(); diff --git a/src/apps/debugger/arch/Architecture.h b/src/apps/debugger/arch/Architecture.h index edb4390676..6cf2167ee2 100644 --- a/src/apps/debugger/arch/Architecture.h +++ b/src/apps/debugger/arch/Architecture.h @@ -13,12 +13,12 @@ class CpuState; +class DisassembledCode; class FunctionDebugInfo; class Image; class ImageDebugInfoProvider; class InstructionInfo; class Register; -class SourceCode; class StackFrame; class StackTrace; class Statement; @@ -57,7 +57,7 @@ public: virtual status_t DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, - SourceCode*& _sourceCode) = 0; + DisassembledCode*& _sourceCode) = 0; virtual status_t GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement) = 0; diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.cpp b/src/apps/debugger/arch/x86/ArchitectureX86.cpp index 497ef94e35..8b93119636 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.cpp +++ b/src/apps/debugger/arch/x86/ArchitectureX86.cpp @@ -271,7 +271,7 @@ ArchitectureX86::UpdateStackFrameCpuState(const StackFrame* frame, status_t ArchitectureX86::DisassembleCode(FunctionDebugInfo* function, - const void* buffer, size_t bufferSize, SourceCode*& _sourceCode) + const void* buffer, size_t bufferSize, DisassembledCode*& _sourceCode) { DisassembledCode* source = new(std::nothrow) DisassembledCode; if (source == NULL) diff --git a/src/apps/debugger/arch/x86/ArchitectureX86.h b/src/apps/debugger/arch/x86/ArchitectureX86.h index 68aac4b4ae..3b31e8240f 100644 --- a/src/apps/debugger/arch/x86/ArchitectureX86.h +++ b/src/apps/debugger/arch/x86/ArchitectureX86.h @@ -35,7 +35,7 @@ public: virtual status_t DisassembleCode(FunctionDebugInfo* function, const void* buffer, size_t bufferSize, - SourceCode*& _sourceCode); + DisassembledCode*& _sourceCode); virtual status_t GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement); diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp index a4d54a6bbd..c37c228717 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp @@ -87,29 +87,6 @@ DebuggerImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function, } -status_t -DebuggerImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode) -{ - // allocate a buffer for the function code - static const target_size_t kMaxBufferSize = 64 * 1024; - target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize); - void* buffer = malloc(bufferSize); - if (buffer == NULL) - return B_NO_MEMORY; - MemoryDeleter bufferDeleter(buffer); - - // read the function code - ssize_t bytesRead = fDebuggerInterface->ReadMemory(function->Address(), - buffer, bufferSize); - if (bytesRead < 0) - return bytesRead; - - return fArchitecture->DisassembleCode(function, buffer, bytesRead, - _sourceCode); -} - - status_t DebuggerImageDebugInfo::GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement) @@ -127,6 +104,22 @@ DebuggerImageDebugInfo::GetStatementAtSourceLocation( } +ssize_t +DebuggerImageDebugInfo::ReadCode(target_addr_t address, void* buffer, + size_t size) +{ + return fDebuggerInterface->ReadMemory(address, buffer, size); +} + + +status_t +DebuggerImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode) +{ + return B_UNSUPPORTED; +} + + /*static*/ int DebuggerImageDebugInfo::_CompareSymbols(const SymbolInfo* a, const SymbolInfo* b) diff --git a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h index e41eb79005..c8ca8e5dbc 100644 --- a/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DebuggerImageDebugInfo.h @@ -31,8 +31,6 @@ public: CpuState* cpuState, StackFrame*& _previousFrame, CpuState*& _previousCpuState); - virtual status_t LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode); virtual status_t GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement); @@ -41,6 +39,12 @@ public: const SourceLocation& sourceLocation, Statement*& _statement); + virtual ssize_t ReadCode(target_addr_t address, void* buffer, + size_t size); + + virtual status_t AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode); + private: static int _CompareSymbols(const SymbolInfo* a, const SymbolInfo* b); diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp index 124b8eba5f..2076d87791 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp @@ -3,8 +3,10 @@ * Distributed under the terms of the MIT License. */ + #include "DwarfImageDebugInfo.h" +#include #include #include @@ -30,84 +32,6 @@ #include "StringUtils.h" -// #pragma mark - SourceCodeEntry - - -struct DwarfImageDebugInfo::SourceCodeKey { - CompilationUnit* unit; - LocatableFile* file; - - SourceCodeKey(CompilationUnit* unit, LocatableFile* file) - : - unit(unit), - file(file) - { - file->AcquireReference(); - } - - ~SourceCodeKey() - { - file->ReleaseReference(); - } - - uint32 HashValue() const - { - return (uint32)((addr_t)unit ^ (addr_t)file); - } - - bool operator==(const SourceCodeKey& other) const - { - return unit == other.unit && file == other.file; - } -}; - - -struct DwarfImageDebugInfo::SourceCodeEntry : SourceCodeKey, - HashTableLink { - FileSourceCode* sourceCode; - - SourceCodeEntry(CompilationUnit* unit, LocatableFile* file, - FileSourceCode* sourceCode) - : - SourceCodeKey(unit, file), - sourceCode(sourceCode) - { - } -}; - - -// #pragma mark - SourceCodeHashDefinition - - -struct DwarfImageDebugInfo::SourceCodeHashDefinition { - typedef SourceCodeKey KeyType; - typedef SourceCodeEntry ValueType; - - size_t HashKey(const SourceCodeKey& key) const - { - return key.HashValue(); - } - - size_t Hash(const SourceCodeEntry* value) const - { - return value->HashValue(); - } - - bool Compare(const SourceCodeKey& key, const SourceCodeEntry* value) const - { - return key == *value; - } - - HashTableLink* GetLink(SourceCodeEntry* value) const - { - return value; - } -}; - - -// #pragma mark - DwarfImageDebugInfo - - DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, Architecture* architecture, FileManager* fileManager, DwarfFile* file) : @@ -117,22 +41,13 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, fFileManager(fileManager), fFile(file), fTextSegment(NULL), - fRelocationDelta(0), - fSourceCodes(NULL) + fRelocationDelta(0) { } DwarfImageDebugInfo::~DwarfImageDebugInfo() { - SourceCodeEntry* entry = fSourceCodes->Clear(true); - while (entry != NULL) { - SourceCodeEntry* next = entry->fNext; - entry->sourceCode->ReleaseReference(); - entry = next; - } - - delete fSourceCodes; } @@ -143,14 +58,6 @@ DwarfImageDebugInfo::Init() if (error != B_OK) return error; - fSourceCodes = new (std::nothrow) SourceCodeTable; - if (fSourceCodes == NULL) - return B_NO_MEMORY; - - error = fSourceCodes->Init(); - if (error != B_OK) - return error; - fTextSegment = fFile->GetElfFile()->TextSegment(); if (fTextSegment == NULL) return B_ENTRY_NOT_FOUND; @@ -286,38 +193,6 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* function, } -status_t -DwarfImageDebugInfo::LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode) -{ - AutoLocker locker(fLock); - - status_t error = _LoadSourceCode(function, _sourceCode); - if (error == B_OK) - return B_OK; - - // fall back to disassembling - - static const target_size_t kMaxBufferSize = 64 * 1024; - target_size_t bufferSize = std::min(function->Size(), kMaxBufferSize); - void* buffer = malloc(bufferSize); - if (buffer == NULL) - return B_NO_MEMORY; - MemoryDeleter bufferDeleter(buffer); - - // read the function code - target_addr_t functionOffset = function->Address() - fRelocationDelta - - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); - ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, bufferSize, - functionOffset); - if (bytesRead < 0) - return bytesRead; - - return fArchitecture->DisassembleCode(function, buffer, bytesRead, - _sourceCode); -} - - status_t DwarfImageDebugInfo::GetStatement(FunctionDebugInfo* _function, target_addr_t address, Statement*& _statement) @@ -489,55 +364,41 @@ printf(" -> found statement!\n"); } -status_t -DwarfImageDebugInfo::_LoadSourceCode(FunctionDebugInfo* _function, - SourceCode*& _sourceCode) +ssize_t +DwarfImageDebugInfo::ReadCode(target_addr_t address, void* buffer, size_t size) { - DwarfFunctionDebugInfo* function - = dynamic_cast(_function); - if (function == NULL) - return B_BAD_VALUE; - - // get the source file - LocatableFile* file = function->SourceFile(); - if (file == NULL) - return B_ENTRY_NOT_FOUND; - - // maybe it's already loaded - CompilationUnit* unit = function->GetCompilationUnit(); - FileSourceCode* sourceCode = _LookupSourceCode(unit, file); - if (sourceCode) { - sourceCode->AcquireReference(); - _sourceCode = sourceCode; - return B_OK; - } - - // get the index of the source file in the compilation unit for cheaper - // comparison below - int32 fileIndex = _GetSourceFileIndex(unit, function->SourceFile()); -printf("DwarfImageDebugInfo::_LoadSourceCode(), file: %ld, function at: %#llx\n", fileIndex, function->Address()); - -for (int32 i = 0; const char* fileName = unit->FileAt(i, NULL); i++) { -printf(" file %ld: %s\n", i, fileName); + target_addr_t offset = address - fRelocationDelta + - fTextSegment->LoadAddress() + fTextSegment->FileOffset(); + ssize_t bytesRead = pread(fFile->GetElfFile()->FD(), buffer, size, offset); + return bytesRead >= 0 ? bytesRead : errno; } - // not loaded yet -- get the source file - SourceFile* sourceFile; - status_t error = fFileManager->LoadSourceFile(file, sourceFile); - if (error != B_OK) - return error; - // create the source code - sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile); - sourceFile->ReleaseReference(); - if (sourceCode == NULL) - return B_NO_MEMORY; +status_t +DwarfImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode) +{ + bool addedAny = false; + for (int32 i = 0; CompilationUnit* unit = fFile->CompilationUnitAt(i); + i++) { + int32 fileIndex = _GetSourceFileIndex(unit, file); + if (fileIndex < 0) + continue; - error = sourceCode->Init(); - if (error != B_OK) - return error; - ObjectDeleter sourceCodeDeleter(sourceCode); + status_t error = _AddSourceCodeInfo(unit, sourceCode, fileIndex); + if (error == B_NO_MEMORY) + return error; + addedAny |= error == B_OK; + } + return addedAny ? B_OK : B_ENTRY_NOT_FOUND; +} + + +status_t +DwarfImageDebugInfo::_AddSourceCodeInfo(CompilationUnit* unit, + FileSourceCode* sourceCode, int32 fileIndex) +{ // Get the statements by executing the line number program for the // compilation unit and filtering the rows for our source file. LineNumberProgram& program = unit->GetLineNumberProgram(); @@ -559,7 +420,7 @@ printf(" %#lx (%ld, %ld, %ld) %d\n", state.address, state.file, state.line, s target_addr_t endAddress = state.address; if (endAddress > statementAddress) { // add the statement - error = sourceCode->AddSourceLocation( + status_t error = sourceCode->AddSourceLocation( SourceLocation(statementLine, statementColumn)); if (error != B_OK) return error; @@ -580,28 +441,10 @@ printf(" -> statement: %#llx - %#llx, source location: (%ld, %ld)\n", statement } } - SourceCodeEntry* entry = new(std::nothrow) SourceCodeEntry(unit, file, - sourceCode); - if (entry == NULL) - return B_NO_MEMORY; - - fSourceCodes->Insert(entry); - - _sourceCode = sourceCodeDeleter.Detach(); - _sourceCode->AcquireReference(); return B_OK; } -FileSourceCode* -DwarfImageDebugInfo::_LookupSourceCode(CompilationUnit* unit, - LocatableFile* file) -{ - SourceCodeEntry* entry = fSourceCodes->Lookup(SourceCodeKey(unit, file)); - return entry != NULL ? entry->sourceCode : NULL; -} - - int32 DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit, LocatableFile* sourceFile) const diff --git a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h index ae6e5f1673..3e024a1d04 100644 --- a/src/apps/debugger/debug_info/DwarfImageDebugInfo.h +++ b/src/apps/debugger/debug_info/DwarfImageDebugInfo.h @@ -5,6 +5,7 @@ #ifndef DWARF_IMAGE_DEBUG_INFO_H #define DWARF_IMAGE_DEBUG_INFO_H + #include #include @@ -42,8 +43,6 @@ public: CpuState* cpuState, StackFrame*& _previousFrame, CpuState*& _previousCpuState); - virtual status_t LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode); virtual status_t GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement); @@ -52,18 +51,16 @@ public: const SourceLocation& sourceLocation, Statement*& _statement); -private: - struct SourceCodeKey; - struct SourceCodeEntry; - struct SourceCodeHashDefinition; + virtual ssize_t ReadCode(target_addr_t address, void* buffer, + size_t size); - typedef OpenHashTable SourceCodeTable; + virtual status_t AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode); private: - status_t _LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode); - FileSourceCode* _LookupSourceCode(CompilationUnit* unit, - LocatableFile* file); + status_t _AddSourceCodeInfo(CompilationUnit* unit, + FileSourceCode* sourceCode, + int32 fileIndex); int32 _GetSourceFileIndex(CompilationUnit* unit, LocatableFile* sourceFile) const; @@ -75,7 +72,6 @@ private: DwarfFile* fFile; ElfSegment* fTextSegment; target_addr_t fRelocationDelta; - SourceCodeTable* fSourceCodes; }; diff --git a/src/apps/debugger/debug_info/Function.cpp b/src/apps/debugger/debug_info/Function.cpp index f99350f861..7acd659ee0 100644 --- a/src/apps/debugger/debug_info/Function.cpp +++ b/src/apps/debugger/debug_info/Function.cpp @@ -5,13 +5,14 @@ #include "Function.h" -#include "SourceCode.h" +#include "FileSourceCode.h" Function::Function() : fSourceCode(NULL), - fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED) + fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED), + fNotificationsDisabled(0) { } @@ -23,7 +24,7 @@ Function::~Function() void -Function::SetSourceCode(SourceCode* source, function_source_state state) +Function::SetSourceCode(FileSourceCode* source, function_source_state state) { if (source == fSourceCode && state == fSourceCodeState) return; @@ -34,14 +35,20 @@ Function::SetSourceCode(SourceCode* source, function_source_state state) fSourceCode = source; fSourceCodeState = state; - if (fSourceCode != NULL) + if (fSourceCode != NULL) { fSourceCode->AddReference(); - // notify listeners - for (ListenerList::Iterator it = fListeners.GetIterator(); - Listener* listener = it.Next();) { - listener->FunctionSourceCodeChanged(this); + // unset all instances' source codes + fNotificationsDisabled++; + for (FunctionInstanceList::Iterator it = fInstances.GetIterator(); + FunctionInstance* instance = it.Next();) { + instance->SetSourceCode(NULL, FUNCTION_SOURCE_NOT_LOADED); + } + fNotificationsDisabled--; } + + // notify listeners + NotifySourceCodeChanged(); } @@ -59,11 +66,9 @@ Function::RemoveListener(Listener* listener) } -#include void Function::AddInstance(FunctionInstance* instance) { -printf(" %p: added %p\n", this, instance); fInstances.Add(instance); } @@ -71,11 +76,23 @@ printf(" %p: added %p\n", this, instance); void Function::RemoveInstance(FunctionInstance* instance) { -printf(" %p: removed %p\n", this, instance); fInstances.Remove(instance); } +void +Function::NotifySourceCodeChanged() +{ + if (fNotificationsDisabled > 0) + return; + + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->FunctionSourceCodeChanged(this); + } +} + + // #pragma mark - Listener diff --git a/src/apps/debugger/debug_info/Function.h b/src/apps/debugger/debug_info/Function.h index 339d830c65..ec40c05e0a 100644 --- a/src/apps/debugger/debug_info/Function.h +++ b/src/apps/debugger/debug_info/Function.h @@ -11,15 +11,7 @@ #include "FunctionInstance.h" -enum function_source_state { - FUNCTION_SOURCE_NOT_LOADED, - FUNCTION_SOURCE_LOADING, - FUNCTION_SOURCE_LOADED, - FUNCTION_SOURCE_UNAVAILABLE -}; - - -class SourceCode; +class FileSourceCode; class Function : public Referenceable, public HashTableLink { @@ -49,10 +41,10 @@ public: ->GetSourceLocation(); } // mutable attributes follow (locking required) - SourceCode* GetSourceCode() const { return fSourceCode; } + FileSourceCode* GetSourceCode() const { return fSourceCode; } function_source_state SourceCodeState() const { return fSourceCodeState; } - void SetSourceCode(SourceCode* source, + void SetSourceCode(FileSourceCode* source, function_source_state state); void AddListener(Listener* listener); @@ -62,14 +54,17 @@ public: void AddInstance(FunctionInstance* instance); void RemoveInstance(FunctionInstance* instance); + void NotifySourceCodeChanged(); + private: typedef DoublyLinkedList ListenerList; private: FunctionInstanceList fInstances; - SourceCode* fSourceCode; + FileSourceCode* fSourceCode; function_source_state fSourceCodeState; ListenerList fListeners; + int32 fNotificationsDisabled; }; diff --git a/src/apps/debugger/debug_info/FunctionInstance.cpp b/src/apps/debugger/debug_info/FunctionInstance.cpp index b5f53f8ca4..6e9c6fe18a 100644 --- a/src/apps/debugger/debug_info/FunctionInstance.cpp +++ b/src/apps/debugger/debug_info/FunctionInstance.cpp @@ -5,6 +5,7 @@ #include "FunctionInstance.h" +#include "DisassembledCode.h" #include "Function.h" @@ -13,7 +14,9 @@ FunctionInstance::FunctionInstance(ImageDebugInfo* imageDebugInfo, : fImageDebugInfo(imageDebugInfo), fFunction(NULL), - fFunctionDebugInfo(functionDebugInfo) + fFunctionDebugInfo(functionDebugInfo), + fSourceCode(NULL), + fSourceCodeState(FUNCTION_SOURCE_NOT_LOADED) { fFunctionDebugInfo->AcquireReference(); // TODO: What about fImageDebugInfo? We must be careful regarding cyclic @@ -39,3 +42,24 @@ FunctionInstance::SetFunction(Function* function) if (fFunction != NULL) fFunction->AcquireReference(); } + + +void +FunctionInstance::SetSourceCode(DisassembledCode* source, + function_source_state state) +{ + if (source == fSourceCode && state == fSourceCodeState) + return; + + if (fSourceCode != NULL) + fSourceCode->RemoveReference(); + + fSourceCode = source; + fSourceCodeState = state; + + if (fSourceCode != NULL) + fSourceCode->AddReference(); + + if (fFunction != NULL) + fFunction->NotifySourceCodeChanged(); +} diff --git a/src/apps/debugger/debug_info/FunctionInstance.h b/src/apps/debugger/debug_info/FunctionInstance.h index 5f9ba669f2..89092c498e 100644 --- a/src/apps/debugger/debug_info/FunctionInstance.h +++ b/src/apps/debugger/debug_info/FunctionInstance.h @@ -10,6 +10,15 @@ #include "FunctionDebugInfo.h" +enum function_source_state { + FUNCTION_SOURCE_NOT_LOADED, + FUNCTION_SOURCE_LOADING, + FUNCTION_SOURCE_LOADED, + FUNCTION_SOURCE_UNAVAILABLE +}; + + +class DisassembledCode; class Function; class FunctionDebugInfo; class ImageDebugInfo; @@ -45,10 +54,21 @@ public: void SetFunction(Function* function); // package private + + // mutable attributes follow (locking required) + DisassembledCode* GetSourceCode() const + { return fSourceCode; } + function_source_state SourceCodeState() const + { return fSourceCodeState; } + void SetSourceCode(DisassembledCode* source, + function_source_state state); + private: ImageDebugInfo* fImageDebugInfo; Function* fFunction; FunctionDebugInfo* fFunctionDebugInfo; + DisassembledCode* fSourceCode; + function_source_state fSourceCodeState; }; diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.cpp b/src/apps/debugger/debug_info/ImageDebugInfo.cpp index 81b8fe3e6e..f337128b22 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.cpp +++ b/src/apps/debugger/debug_info/ImageDebugInfo.cpp @@ -96,6 +96,23 @@ ImageDebugInfo::FunctionAtAddress(target_addr_t address) const } +status_t +ImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode) const +{ + bool addedAny = false; + for (int32 i = 0; SpecificImageDebugInfo* specificInfo + = fSpecificInfos.ItemAt(i); i++) { + status_t error = specificInfo->AddSourceCodeInfo(file, sourceCode); + if (error == B_NO_MEMORY) + return error; + addedAny |= error == B_OK; + } + + return addedAny ? B_OK : B_ENTRY_NOT_FOUND; +} + + /*static*/ int ImageDebugInfo::_CompareFunctions(const FunctionInstance* a, const FunctionInstance* b) diff --git a/src/apps/debugger/debug_info/ImageDebugInfo.h b/src/apps/debugger/debug_info/ImageDebugInfo.h index 2bc9f44c2f..2f934d249c 100644 --- a/src/apps/debugger/debug_info/ImageDebugInfo.h +++ b/src/apps/debugger/debug_info/ImageDebugInfo.h @@ -16,8 +16,10 @@ class Architecture; class DebuggerInterface; +class FileSourceCode; class FunctionDebugInfo; class FunctionInstance; +class LocatableFile; class SpecificImageDebugInfo; @@ -33,6 +35,9 @@ public: FunctionInstance* FunctionAt(int32 index) const; FunctionInstance* FunctionAtAddress(target_addr_t address) const; + status_t AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode) const; + private: typedef BObjectList SpecificInfoList; typedef BObjectList FunctionList; diff --git a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h index b9c0442dfd..012b328ef8 100644 --- a/src/apps/debugger/debug_info/SpecificImageDebugInfo.h +++ b/src/apps/debugger/debug_info/SpecificImageDebugInfo.h @@ -14,9 +14,10 @@ class Architecture; class CpuState; class DebuggerInterface; +class FileSourceCode; class FunctionDebugInfo; class Image; -class SourceCode; +class LocatableFile; class SourceLocation; class StackFrame; class Statement; @@ -39,9 +40,6 @@ public: // returns reference to previous frame // and CPU state; returned CPU state // can be NULL; can return B_UNSUPPORTED - virtual status_t LoadSourceCode(FunctionDebugInfo* function, - SourceCode*& _sourceCode) = 0; - // returns reference virtual status_t GetStatement(FunctionDebugInfo* function, target_addr_t address, Statement*& _statement) = 0; @@ -51,6 +49,12 @@ public: const SourceLocation& sourceLocation, Statement*& _statement) = 0; // returns reference + + virtual ssize_t ReadCode(target_addr_t address, void* buffer, + size_t size) = 0; + + virtual status_t AddSourceCodeInfo(LocatableFile* file, + FileSourceCode* sourceCode) = 0; }; diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.cpp b/src/apps/debugger/debug_info/TeamDebugInfo.cpp index 625106e481..18cd439af2 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.cpp +++ b/src/apps/debugger/debug_info/TeamDebugInfo.cpp @@ -11,12 +11,18 @@ #include #include +#include +#include "Architecture.h" #include "DebuggerTeamDebugInfo.h" +#include "DisassembledCode.h" #include "DwarfTeamDebugInfo.h" +#include "FileManager.h" +#include "FileSourceCode.h" #include "Function.h" #include "ImageDebugInfo.h" #include "LocatableFile.h" +#include "SourceFile.h" #include "SpecificImageDebugInfo.h" #include "StringUtils.h" @@ -76,13 +82,15 @@ struct TeamDebugInfo::FunctionHashDefinition { struct TeamDebugInfo::SourceFileEntry : public HashTableLink { SourceFileEntry(LocatableFile* sourceFile) : - fSourceFile(sourceFile) + fSourceFile(sourceFile), + fSourceCode(NULL) { fSourceFile->AcquireReference(); } ~SourceFileEntry() { + SetSourceCode(NULL); fSourceFile->ReleaseReference(); } @@ -96,6 +104,26 @@ struct TeamDebugInfo::SourceFileEntry : public HashTableLink { return fSourceFile; } + FileSourceCode* GetSourceCode() const + { + return fSourceCode; + } + + void SetSourceCode(FileSourceCode* sourceCode) + { + if (sourceCode == fSourceCode) + return; + + if (fSourceCode != NULL) + fSourceCode->ReleaseReference(); + + fSourceCode = sourceCode; + + if (fSourceCode != NULL) + fSourceCode->AcquireReference(); + } + + bool IsUnused() const { return fFunctions.IsEmpty(); @@ -162,6 +190,7 @@ private: private: LocatableFile* fSourceFile; + FileSourceCode* fSourceCode; FunctionList fFunctions; }; @@ -201,6 +230,7 @@ struct TeamDebugInfo::SourceFileHashDefinition { TeamDebugInfo::TeamDebugInfo(DebuggerInterface* debuggerInterface, Architecture* architecture, FileManager* fileManager) : + fLock("team debug info"), fDebuggerInterface(debuggerInterface), fArchitecture(architecture), fFileManager(fileManager), @@ -240,12 +270,17 @@ TeamDebugInfo::~TeamDebugInfo() status_t TeamDebugInfo::Init() { + // check the lock + status_t error = fLock.InitCheck(); + if (error != B_OK) + return error; + // create function hash table fFunctions = new(std::nothrow) FunctionTable; if (fFunctions == NULL) return B_NO_MEMORY; - status_t error = fFunctions->Init(); + error = fFunctions->Init(); if (error != B_OK) return error; @@ -324,12 +359,103 @@ TeamDebugInfo::LoadImageDebugInfo(const ImageInfo& imageInfo, } -#include +status_t +TeamDebugInfo::LoadSourceCode(LocatableFile* file, FileSourceCode*& _sourceCode) +{ + AutoLocker locker(fLock); + + // If we don't know the source file, there's nothing we can do. + SourceFileEntry* entry = fSourceFiles->Lookup(file); + if (entry == NULL) + return B_ENTRY_NOT_FOUND; + + // the source might already be loaded + FileSourceCode* sourceCode = entry->GetSourceCode(); + if (sourceCode != NULL) { + sourceCode->AcquireReference(); + _sourceCode = sourceCode; + return B_OK; + } + + // no source code yet +// locker.Unlock(); + // TODO: It would be nice to unlock here, but we need to iterate through + // the images below. We could clone the list, acquire references, and + // unlock. Then we have to compare the list with the then current list when + // we're done loading. + + // load the source file + SourceFile* sourceFile; + status_t error = fFileManager->LoadSourceFile(file, sourceFile); + if (error != B_OK) + return error; + + // create the source code + sourceCode = new(std::nothrow) FileSourceCode(file, sourceFile); + sourceFile->ReleaseReference(); + if (sourceCode == NULL) + return B_NO_MEMORY; + Reference sourceCodeReference(sourceCode, true); + + error = sourceCode->Init(); + if (error != B_OK) + return error; + + // Iterate through all images that know the source file and ask them to add + // information. + bool anyInfo = false; + for (int32 i = 0; ImageDebugInfo* imageDebugInfo = fImages.ItemAt(i); i++) + anyInfo |= imageDebugInfo->AddSourceCodeInfo(file, sourceCode) == B_OK; + + if (!anyInfo) + return B_ENTRY_NOT_FOUND; + + entry->SetSourceCode(sourceCode); + + _sourceCode = sourceCodeReference.Detach(); + return B_OK; +} + + +status_t +TeamDebugInfo::DisassembleFunction(FunctionInstance* functionInstance, + DisassembledCode*& _sourceCode) +{ + // allocate a buffer for the function code + static const target_size_t kMaxBufferSize = 64 * 1024; + target_size_t bufferSize = std::min(functionInstance->Size(), + kMaxBufferSize); + void* buffer = malloc(bufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + MemoryDeleter bufferDeleter(buffer); + + // read the function code + FunctionDebugInfo* functionDebugInfo + = functionInstance->GetFunctionDebugInfo(); + ssize_t bytesRead = functionDebugInfo->GetSpecificImageDebugInfo() + ->ReadCode(functionInstance->Address(), buffer, bufferSize); + if (bytesRead < 0) + return bytesRead; + + return fArchitecture->DisassembleCode(functionDebugInfo, buffer, bytesRead, + _sourceCode); +} + + status_t TeamDebugInfo::AddImageDebugInfo(ImageDebugInfo* imageDebugInfo) { printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo); + AutoLocker locker(fLock); + // We have both locks now, so that for read-only access either lock + // suffices. + + if (!fImages.AddItem(imageDebugInfo)) + return B_NO_MEMORY; + // Match all of the image debug info's functions instances with functions. + BObjectList sourceFileEntries; for (int32 i = 0; FunctionInstance* instance = imageDebugInfo->FunctionAt(i); i++) { // lookup the function or create it, if it doesn't exist yet @@ -339,6 +465,15 @@ printf("TeamDebugInfo::AddImageDebugInfo(%p)\n", imageDebugInfo); printf(" adding instance %p to existing function %p\n", instance, function); function->AddInstance(instance); instance->SetFunction(function); + + // The new image debug info might have additional information about + // the source file of the function, so remember the source file + // entry. + if (LocatableFile* sourceFile = function->SourceFile()) { + SourceFileEntry* entry = fSourceFiles->Lookup(sourceFile); + if (entry != NULL && entry->GetSourceCode() != NULL) + sourceFileEntries.AddItem(entry); + } } else { function = new(std::nothrow) Function; if (function == NULL) { @@ -361,6 +496,19 @@ printf(" adding instance %p to new function %p\n", instance, function); } } + // update the source files the image debug info knows about + for (int32 i = 0; SourceFileEntry* entry = sourceFileEntries.ItemAt(i); + i++) { + FileSourceCode* sourceCode = entry->GetSourceCode(); + sourceCode->Lock(); + if (imageDebugInfo->AddSourceCodeInfo(entry->SourceFile(), + sourceCode) == B_OK) { + // TODO: Notify interesting parties! Iterate through all functions + // for this source file? + } + sourceCode->Unlock(); + } + return B_OK; } @@ -368,6 +516,10 @@ printf(" adding instance %p to new function %p\n", instance, function); void TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo) { + AutoLocker locker(fLock); + // We have both locks now, so that for read-only access either lock + // suffices. + // Remove the functions from all of the image debug info's functions // instances. for (int32 i = 0; @@ -390,6 +542,8 @@ TeamDebugInfo::RemoveImageDebugInfo(ImageDebugInfo* imageDebugInfo) // reference to the function. } } + + fImages.RemoveItem(imageDebugInfo); } diff --git a/src/apps/debugger/debug_info/TeamDebugInfo.h b/src/apps/debugger/debug_info/TeamDebugInfo.h index 6c5ea69546..dc04e436e8 100644 --- a/src/apps/debugger/debug_info/TeamDebugInfo.h +++ b/src/apps/debugger/debug_info/TeamDebugInfo.h @@ -6,6 +6,8 @@ #define TEAM_DEBUG_INFO_H +#include + #include #include #include @@ -15,12 +17,15 @@ class Architecture; class DebuggerInterface; +class DisassembledCode; class FileManager; +class FileSourceCode; class Function; class FunctionInstance; class ImageDebugInfo; class ImageInfo; class LocatableFile; +class SourceCode; class SourceLocation; class SpecificTeamDebugInfo; @@ -39,6 +44,15 @@ public: LocatableFile* imageFile, ImageDebugInfo*& _imageDebugInfo); + status_t LoadSourceCode(LocatableFile* file, + FileSourceCode*& _sourceCode); + // returns reference + status_t DisassembleFunction( + FunctionInstance* functionInstance, + DisassembledCode*& _sourceCode); + // returns reference + + // team is locked status_t AddImageDebugInfo( ImageDebugInfo* imageDebugInfo); @@ -54,6 +68,7 @@ private: struct SourceFileHashDefinition; typedef BObjectList SpecificInfoList; + typedef BObjectList ImageList; typedef OpenHashTable FunctionTable; typedef OpenHashTable SourceFileTable; @@ -62,10 +77,12 @@ private: void _RemoveFunction(Function* function); private: + BLocker fLock; DebuggerInterface* fDebuggerInterface; Architecture* fArchitecture; FileManager* fFileManager; SpecificInfoList fSpecificInfos; + ImageList fImages; FunctionTable* fFunctions; SourceFileTable* fSourceFiles; }; diff --git a/src/apps/debugger/gui/team_window/SourceView.cpp b/src/apps/debugger/gui/team_window/SourceView.cpp index a1a8b166d9..5c6d90a4ff 100644 --- a/src/apps/debugger/gui/team_window/SourceView.cpp +++ b/src/apps/debugger/gui/team_window/SourceView.cpp @@ -20,8 +20,9 @@ #include #include "Breakpoint.h" +#include "DisassembledCode.h" #include "Function.h" -#include "SourceCode.h" +#include "FileSourceCode.h" #include "StackTrace.h" #include "Statement.h" #include "TeamDebugModel.h" @@ -503,6 +504,8 @@ SourceView::MarkerView::Draw(BRect updateRect) float width = Bounds().Width(); + AutoLocker sourceLocker(fSourceCode); + int32 markerIndex = 0; for (int32 line = minLine; line <= maxLine; line++) { bool drawBreakpointOptionMarker = true; @@ -518,7 +521,6 @@ SourceView::MarkerView::Draw(BRect updateRect) if (!drawBreakpointOptionMarker) continue; - SourceLocation statementStart, statementEnd; if (!fSourceCode->GetStatementLocationRange(SourceLocation(line), statementStart, statementEnd) @@ -600,6 +602,8 @@ SourceView::MarkerView::_UpdateIPMarkers() fIPMarkers.MakeEmpty(); if (fSourceCode != NULL && fStackTrace != NULL) { + LocatableFile* sourceFile = fSourceCode->GetSourceFile(); + AutoLocker locker(fDebugModel); for (int32 i = 0; StackFrame* frame = fStackTrace->FrameAt(i); @@ -614,7 +618,9 @@ SourceView::MarkerView::_UpdateIPMarkers() Reference statementReference(statement, true); uint32 line = statement->StartSourceLocation().Line(); - if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode + if ((functionInstance->GetSourceCode() != fSourceCode + && functionInstance->GetFunction()->SourceFile() + != sourceFile) || line < 0 || line >= (uint32)LineCount()) { continue; } @@ -649,6 +655,8 @@ SourceView::MarkerView::_UpdateBreakpointMarkers() fBreakpointMarkers.MakeEmpty(); if (fSourceCode != NULL) { + LocatableFile* sourceFile = fSourceCode->GetSourceFile(); + AutoLocker locker(fDebugModel); // get the breakpoints in our source code range @@ -669,7 +677,9 @@ SourceView::MarkerView::_UpdateBreakpointMarkers() Reference statementReference(statement, true); uint32 line = statement->StartSourceLocation().Line(); - if (functionInstance->GetFunction()->GetSourceCode() != fSourceCode + if ((functionInstance->GetSourceCode() != fSourceCode + && functionInstance->GetFunction()->SourceFile() + != sourceFile) || line < 0 || line >= (uint32)LineCount()) { continue; } diff --git a/src/apps/debugger/gui/team_window/TeamWindow.cpp b/src/apps/debugger/gui/team_window/TeamWindow.cpp index 07f900a232..35cf639289 100644 --- a/src/apps/debugger/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/gui/team_window/TeamWindow.cpp @@ -18,11 +18,12 @@ #include #include "CpuState.h" +#include "DisassembledCode.h" +#include "FileSourceCode.h" #include "Image.h" #include "ImageDebugInfo.h" #include "MessageCodes.h" #include "RegisterView.h" -#include "SourceCode.h" #include "StackTrace.h" #include "StackTraceView.h" @@ -505,6 +506,8 @@ TeamWindow::_SetActiveFunction(FunctionInstance* functionInstance) Function* function = fActiveFunction->GetFunction(); sourceCode = function->GetSourceCode(); + if (sourceCode == NULL) + sourceCode = fActiveFunction->GetSourceCode(); sourceCodeReference.SetTo(sourceCode); // If the source code is not loaded yet, request it. @@ -703,6 +706,8 @@ TeamWindow::_HandleSourceCodeChanged() AutoLocker locker(fDebugModel); SourceCode* sourceCode = fActiveFunction->GetFunction()->GetSourceCode(); + if (sourceCode == NULL) + sourceCode = fActiveFunction->GetSourceCode(); Reference sourceCodeReference(sourceCode); locker.Unlock(); diff --git a/src/apps/debugger/model/Breakpoint.h b/src/apps/debugger/model/Breakpoint.h index 06639fd79e..c44f3f967b 100644 --- a/src/apps/debugger/model/Breakpoint.h +++ b/src/apps/debugger/model/Breakpoint.h @@ -36,6 +36,8 @@ public: { return fUserBreakpoints.Head(); } UserBreakpointInstance* LastUserBreakpoint() const { return fUserBreakpoints.Tail(); } + const UserBreakpointInstanceList& UserBreakpoints() const + { return fUserBreakpoints; } void AddUserBreakpoint( UserBreakpointInstance* instance); diff --git a/src/apps/debugger/model/DisassembledCode.cpp b/src/apps/debugger/model/DisassembledCode.cpp index c83b06a5fc..599f9a43c4 100644 --- a/src/apps/debugger/model/DisassembledCode.cpp +++ b/src/apps/debugger/model/DisassembledCode.cpp @@ -43,6 +43,20 @@ DisassembledCode::~DisassembledCode() } +bool +DisassembledCode::Lock() +{ + // We're immutable, so no locking required. + return true; +} + + +void +DisassembledCode::Unlock() +{ +} + + int32 DisassembledCode::CountLines() const { @@ -80,17 +94,32 @@ DisassembledCode::GetSourceFile() const } -status_t -DisassembledCode::GetStatementAtLocation(const SourceLocation& location, - Statement*& _statement) +Statement* +DisassembledCode::StatementAtLocation(const SourceLocation& location) const { Line* line = fLines.ItemAt(location.Line()); - if (line == NULL || line->statement == NULL) - return B_ENTRY_NOT_FOUND; + return line != NULL ? line->statement : NULL; +} - _statement = line->statement; - _statement->AcquireReference(); - return B_OK; + +Statement* +DisassembledCode::StatementAtAddress(target_addr_t address) const +{ + return fStatements.BinarySearchByKey(address, &_CompareAddressStatement); +} + + +TargetAddressRange +DisassembledCode::StatementAddressRange() const +{ + if (fStatements.IsEmpty()) + return TargetAddressRange(); + + ContiguousStatement* first = fStatements.ItemAt(0); + ContiguousStatement* last + = fStatements.ItemAt(fStatements.CountItems() - 1); + return TargetAddressRange(first->AddressRange().Start(), + last->AddressRange().End()); } diff --git a/src/apps/debugger/model/DisassembledCode.h b/src/apps/debugger/model/DisassembledCode.h index 11f1a3a4d3..9afd21757e 100644 --- a/src/apps/debugger/model/DisassembledCode.h +++ b/src/apps/debugger/model/DisassembledCode.h @@ -20,6 +20,9 @@ public: DisassembledCode(); ~DisassembledCode(); + virtual bool Lock(); + virtual void Unlock(); + virtual int32 CountLines() const; virtual const char* LineAt(int32 index) const; @@ -30,9 +33,10 @@ public: virtual LocatableFile* GetSourceFile() const; - virtual status_t GetStatementAtLocation( - const SourceLocation& location, - Statement*& _statement); + Statement* StatementAtAddress(target_addr_t address) const; + Statement* StatementAtLocation( + const SourceLocation& location) const; + TargetAddressRange StatementAddressRange() const; public: bool AddCommentLine(const BString& line); diff --git a/src/apps/debugger/model/FileSourceCode.cpp b/src/apps/debugger/model/FileSourceCode.cpp index 5800998124..327222af7c 100644 --- a/src/apps/debugger/model/FileSourceCode.cpp +++ b/src/apps/debugger/model/FileSourceCode.cpp @@ -15,6 +15,7 @@ FileSourceCode::FileSourceCode(LocatableFile* file, SourceFile* sourceFile) : + fLock("source code"), fFile(file), fSourceFile(sourceFile) { @@ -33,7 +34,7 @@ FileSourceCode::~FileSourceCode() status_t FileSourceCode::Init() { - return B_OK; + return fLock.InitCheck(); } @@ -50,6 +51,20 @@ FileSourceCode::AddSourceLocation(const SourceLocation& location) } +bool +FileSourceCode::Lock() +{ + return fLock.Lock(); +} + + +void +FileSourceCode::Unlock() +{ + fLock.Unlock(); +} + + int32 FileSourceCode::CountLines() const { @@ -95,14 +110,6 @@ FileSourceCode::GetSourceFile() const } -status_t -FileSourceCode::GetStatementAtLocation(const SourceLocation& location, - Statement*& _statement) -{ - return B_UNSUPPORTED; -} - - int32 FileSourceCode::_FindSourceLocationIndex(const SourceLocation& location, bool& _foundMatch) const diff --git a/src/apps/debugger/model/FileSourceCode.h b/src/apps/debugger/model/FileSourceCode.h index 81a5b0bc1e..9a56ec7034 100644 --- a/src/apps/debugger/model/FileSourceCode.h +++ b/src/apps/debugger/model/FileSourceCode.h @@ -6,6 +6,9 @@ #define FILE_SOURCE_CODE_H +#include + + #include "Array.h" #include "SourceCode.h" @@ -24,6 +27,9 @@ public: status_t AddSourceLocation( const SourceLocation& location); + virtual bool Lock(); + virtual void Unlock(); + virtual int32 CountLines() const; virtual const char* LineAt(int32 index) const; @@ -34,16 +40,13 @@ public: virtual LocatableFile* GetSourceFile() const; - virtual status_t GetStatementAtLocation( - const SourceLocation& location, - Statement*& _statement); - private: int32 _FindSourceLocationIndex( const SourceLocation& location, bool& _foundMatch) const; private: + BLocker fLock; LocatableFile* fFile; SourceFile* fSourceFile; Array fSourceLocations; diff --git a/src/apps/debugger/model/SourceCode.h b/src/apps/debugger/model/SourceCode.h index 0b8dff4644..965828cc8d 100644 --- a/src/apps/debugger/model/SourceCode.h +++ b/src/apps/debugger/model/SourceCode.h @@ -20,6 +20,11 @@ class SourceCode : public Referenceable { public: virtual ~SourceCode(); + // Locking needed for GetStatementLocationRange(), since that might use + // mutable data. + virtual bool Lock() = 0; + virtual void Unlock() = 0; + virtual int32 CountLines() const = 0; virtual const char* LineAt(int32 index) const = 0; @@ -29,13 +34,6 @@ public: SourceLocation& _end) const = 0; virtual LocatableFile* GetSourceFile() const = 0; - - virtual status_t GetStatementAtLocation( - const SourceLocation& location, - Statement*& _statement) = 0; - // returns a reference, - // may return B_UNSUPPORTED, when - // SourceFile() returns non-NULL }; diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index c093159f0c..20889a8dc0 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -11,10 +11,12 @@ #include +#include "DisassembledCode.h" #include "Function.h" #include "ImageDebugInfo.h" #include "SourceCode.h" #include "SpecificImageDebugInfo.h" +#include "Statement.h" #include "TeamDebugInfo.h" @@ -236,12 +238,23 @@ printf(" -> no function instance\n"); return B_ENTRY_NOT_FOUND; } + // If the function instance has disassembled code attached, we can get the + // statement directly. + if (DisassembledCode* code = functionInstance->GetSourceCode()) { + Statement* statement = code->StatementAtAddress(address); + if (statement != NULL) { + statement->AcquireReference(); + _statement = statement; + _function = functionInstance; + return B_OK; + } + } + // get the statement from the image debug info FunctionDebugInfo* functionDebugInfo = functionInstance->GetFunctionDebugInfo(); status_t error = functionDebugInfo->GetSpecificImageDebugInfo() ->GetStatement(functionDebugInfo, address, _statement); - // TODO: Provide the corresponding SourceCode, if available! if (error != B_OK) { printf(" -> no statement from the specific image debug info\n"); @@ -259,9 +272,15 @@ Team::GetStatementAtSourceLocation(SourceCode* sourceCode, { printf("Team::GetStatementAtSourceLocation(%p, (%ld, %ld))\n", sourceCode, location.Line(), location.Column()); // If we're lucky the source code can provide us with a statement. - status_t error = sourceCode->GetStatementAtLocation(location, _statement); - if (error == B_OK) - return error; + if (DisassembledCode* code = dynamic_cast(sourceCode)) { + Statement* statement = code->StatementAtLocation(location); + if (statement == NULL) + return B_ENTRY_NOT_FOUND; + + statement->AcquireReference(); + _statement = statement; + return B_OK; + } // Go the long and stony way over the source file and the team debug info. // get the source file for the source code diff --git a/src/apps/debugger/model/TeamDebugModel.cpp b/src/apps/debugger/model/TeamDebugModel.cpp index 89b54e2692..e6607bf30a 100644 --- a/src/apps/debugger/model/TeamDebugModel.cpp +++ b/src/apps/debugger/model/TeamDebugModel.cpp @@ -10,6 +10,8 @@ #include #include "Breakpoint.h" +#include "DisassembledCode.h" +#include "FileSourceCode.h" #include "Function.h" #include "UserBreakpoint.h" @@ -109,24 +111,42 @@ TeamDebugModel::BreakpointAtAddress(target_addr_t address) const } -//void -//TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range, -// BObjectList& breakpoints) const -//{ -// int32 index = fBreakpoints.FindBinaryInsertionIndex( -// BreakpointByAddressPredicate(range.Start())); -// for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) { -// if (breakpoint->Address() > range.End()) -// break; -// breakpoints.AddItem(breakpoint); -// } -//} +void +TeamDebugModel::GetBreakpointsInAddressRange(TargetAddressRange range, + BObjectList& breakpoints) const +{ + int32 index = fBreakpoints.FindBinaryInsertionIndex( + BreakpointByAddressPredicate(range.Start())); + for (; Breakpoint* breakpoint = fBreakpoints.ItemAt(index); index++) { + if (breakpoint->Address() > range.End()) + break; + + for (UserBreakpointInstanceList::ConstIterator it + = breakpoint->UserBreakpoints().GetIterator(); + UserBreakpointInstance* instance = it.Next();) { + breakpoints.AddItem(instance->GetUserBreakpoint()); + } + } + + // TODO: Avoid duplicates! +} void TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode, BObjectList& breakpoints) const { + if (DisassembledCode* disassembledCode + = dynamic_cast(sourceCode)) { + GetBreakpointsInAddressRange(disassembledCode->StatementAddressRange(), + breakpoints); + return; + } + + LocatableFile* sourceFile = sourceCode->GetSourceFile(); + if (sourceFile == NULL) + return; + // TODO: This can probably be optimized. Maybe by registering the user // breakpoints with the team debug model and sorting them by source code. for (int32 i = 0; Breakpoint* breakpoint = fBreakpoints.ItemAt(i); i++) { @@ -137,7 +157,7 @@ TeamDebugModel::GetBreakpointsForSourceCode(SourceCode* sourceCode, UserBreakpoint* userBreakpoint = userBreakpointInstance->GetUserBreakpoint(); - if (userBreakpoint->GetFunction()->GetSourceCode() == sourceCode) + if (userBreakpoint->GetFunction()->SourceFile() == sourceFile) breakpoints.AddItem(userBreakpoint); } } diff --git a/src/apps/debugger/model/TeamDebugModel.h b/src/apps/debugger/model/TeamDebugModel.h index 8177a264ae..2ae9d43396 100644 --- a/src/apps/debugger/model/TeamDebugModel.h +++ b/src/apps/debugger/model/TeamDebugModel.h @@ -58,9 +58,10 @@ public: Breakpoint* BreakpointAt(int32 index) const; Breakpoint* BreakpointAtAddress( target_addr_t address) const; -// void GetBreakpointsInAddressRange( -// TargetAddressRange range, -// BObjectList& breakpoints) const; + void GetBreakpointsInAddressRange( + TargetAddressRange range, + BObjectList& breakpoints) + const; void GetBreakpointsForSourceCode( SourceCode* sourceCode, BObjectList& breakpoints)