From 18ca318a3d814fb5c61218b6097db8dd6b4fe0a4 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 11 Jul 2009 00:05:26 +0000 Subject: [PATCH] * Since disassembled code is actually function instance specific, FunctionInstance does now also have a (DisassembledCode) source code attribute. Function keeps its attribute, but it explicitly is a FileSourceCode now. * SourceCode: - Removed GetStatementAtLocation(). Instead DisassembledCode has a StatementAtLocation() now. As well as a StatementAtAddress() and StatementAddressRange(). Rather cast to the subclass (in two instances) instead of having those methods in the base class. In most cases we already have the subclasses now, anyway. - Added Lock()/Unlock(), which are implemented in FileSourceCode. The statement ranges are no longer immutable, so we have to lock. * TeamDebugModel: - Revived GetBreakpointsInAddressRange(). - GetBreakpointsForSourceCode(): Optimized for DisassembledCode and fixed in the FileSourceCode case. We need to compare with the functions' source file instead of their source code, since they might not have the source code set yet. Fixed two instances of the same problem in SourceView. Setting breakpoints in functions that have no associated source code yet, works now. * Team: - GetStatementAtAddress(): Optimized by using the DisassembledCode, if available. - GetStatementAtSourceLocation(): If the supplied source code is DisassembledCode, we have to get the statement from it directly, since we can't get that information from the image debug info. * TeamDebugInfo: Added LoadSourceCode() and DisassembleFunction(), the new way to get FileSourceCode respectively DisassembledCode. SpecificTeamDebugInfo has lost LoadSourceCode() and gained service methods AddSourceCodeInfo() and ReadCode(). This avoids unnecessary code duplication in the subclasses. Moreover it allows for joining source location info source files from different images (and compilation units) -- interesting for inline functions in headers. * Adjusted LoadSourceCodeJob and TeamDebugger::FunctionSourceCodeRequested() accordingly. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31514 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/debugger/Jobs.cpp | 64 +++-- src/apps/debugger/Jobs.h | 7 +- src/apps/debugger/TeamDebugger.cpp | 18 +- src/apps/debugger/arch/Architecture.h | 4 +- .../debugger/arch/x86/ArchitectureX86.cpp | 2 +- src/apps/debugger/arch/x86/ArchitectureX86.h | 2 +- .../debug_info/DebuggerImageDebugInfo.cpp | 39 ++- .../debug_info/DebuggerImageDebugInfo.h | 8 +- .../debug_info/DwarfImageDebugInfo.cpp | 223 +++--------------- .../debugger/debug_info/DwarfImageDebugInfo.h | 20 +- src/apps/debugger/debug_info/Function.cpp | 39 ++- src/apps/debugger/debug_info/Function.h | 19 +- .../debugger/debug_info/FunctionInstance.cpp | 26 +- .../debugger/debug_info/FunctionInstance.h | 20 ++ .../debugger/debug_info/ImageDebugInfo.cpp | 17 ++ src/apps/debugger/debug_info/ImageDebugInfo.h | 5 + .../debug_info/SpecificImageDebugInfo.h | 12 +- .../debugger/debug_info/TeamDebugInfo.cpp | 160 ++++++++++++- src/apps/debugger/debug_info/TeamDebugInfo.h | 17 ++ .../debugger/gui/team_window/SourceView.cpp | 18 +- .../debugger/gui/team_window/TeamWindow.cpp | 7 +- src/apps/debugger/model/Breakpoint.h | 2 + src/apps/debugger/model/DisassembledCode.cpp | 45 +++- src/apps/debugger/model/DisassembledCode.h | 10 +- src/apps/debugger/model/FileSourceCode.cpp | 25 +- src/apps/debugger/model/FileSourceCode.h | 11 +- src/apps/debugger/model/SourceCode.h | 12 +- src/apps/debugger/model/Team.cpp | 27 ++- src/apps/debugger/model/TeamDebugModel.cpp | 46 +++- src/apps/debugger/model/TeamDebugModel.h | 7 +- 30 files changed, 564 insertions(+), 348 deletions(-) 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)