diff options
| author | Rene Gollent <anevilyak@gmail.com> | 2012-07-29 07:07:04 -0400 |
|---|---|---|
| committer | Rene Gollent <anevilyak@gmail.com> | 2012-07-29 07:12:49 -0400 |
| commit | 224f75100b15ee71dce0b0e551efd40236ca8b54 (patch) | |
| tree | a7a01aa2631b5ef26af00c5f7fbc14f706972e86 | |
| parent | 200dec066fdd9d18e8e93232a6e55e9f5ba3df30 (diff) | |
Implement support for separate debug info files.hrev44428
- When loading an image, we now check if it has a .gnu_debuglink section.
If so, we try to load the linked file for our symbolic debugging information.
The file is searched for with the following rules:
1) If self-contained app, app image is looked for in ./debug while
library/add-on images are looked for in ../debug/.
2) If the image in question is in one of the global locations
(/boot/{common,system,home/config}/{lib,add-ons}), we search
in develop/debug for the corresponding global dir.
Implements #8135.
| -rw-r--r-- | src/apps/debugger/dwarf/DwarfFile.cpp | 183 | ||||
| -rw-r--r-- | src/apps/debugger/dwarf/DwarfFile.h | 6 |
2 files changed, 167 insertions, 22 deletions
diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp index f95d18ea4a..636b1fa937 100644 --- a/src/apps/debugger/dwarf/DwarfFile.cpp +++ b/src/apps/debugger/dwarf/DwarfFile.cpp @@ -11,6 +11,9 @@ #include <new> #include <AutoDeleter.h> +#include <Entry.h> +#include <FindDirectory.h> +#include <Path.h> #include "AttributeClasses.h" #include "AttributeValue.h" @@ -27,6 +30,30 @@ #include "Variant.h" +// #pragma mark - AutoSectionPutter + + +class AutoSectionPutter { +public: + AutoSectionPutter(ElfFile* elfFile, ElfSection* elfSection) + : + fElfFile(elfFile), + fElfSection(elfSection) + { + } + + ~AutoSectionPutter() + { + if (fElfSection != NULL) + fElfFile->PutSection(fElfSection); + } + +private: + ElfFile* fElfFile; + ElfSection* fElfSection; +}; + + // #pragma mark - ExpressionEvaluationContext @@ -281,7 +308,9 @@ private: DwarfFile::DwarfFile() : fName(NULL), + fAlternateName(NULL), fElfFile(NULL), + fAlternateElfFile(NULL), fDebugInfoSection(NULL), fDebugAbbrevSection(NULL), fDebugStringSection(NULL), @@ -305,19 +334,24 @@ DwarfFile::~DwarfFile() delete table; if (fElfFile != NULL) { - fElfFile->PutSection(fDebugInfoSection); - fElfFile->PutSection(fDebugAbbrevSection); - fElfFile->PutSection(fDebugStringSection); - fElfFile->PutSection(fDebugRangesSection); - fElfFile->PutSection(fDebugLineSection); - fElfFile->PutSection(fDebugFrameSection); + ElfFile* debugInfoFile = fAlternateElfFile != NULL + ? fAlternateElfFile : fElfFile; + + debugInfoFile->PutSection(fDebugInfoSection); + debugInfoFile->PutSection(fDebugAbbrevSection); + debugInfoFile->PutSection(fDebugStringSection); + debugInfoFile->PutSection(fDebugRangesSection); + debugInfoFile->PutSection(fDebugLineSection); + debugInfoFile->PutSection(fDebugFrameSection); fElfFile->PutSection(fEHFrameSection); - fElfFile->PutSection(fDebugLocationSection); - fElfFile->PutSection(fDebugPublicTypesSection); + debugInfoFile->PutSection(fDebugLocationSection); + debugInfoFile->PutSection(fDebugPublicTypesSection); delete fElfFile; + delete fAlternateElfFile; } free(fName); + free(fAlternateName); } @@ -337,23 +371,24 @@ DwarfFile::Load(const char* fileName) if (error != B_OK) return error; - // get the interesting sections - fDebugInfoSection = fElfFile->GetSection(".debug_info"); - fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev"); - if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) { - WARNING("DwarfManager::File::Load(\"%s\"): no " - ".debug_info or .debug_abbrev.\n", fileName); - return B_ERROR; - } + error = _LocateDebugInfo(); + if (error != B_OK) + return error; + + ElfFile* debugInfoFile = fAlternateElfFile != NULL + ? fAlternateElfFile : fElfFile; // non mandatory sections - fDebugStringSection = fElfFile->GetSection(".debug_str"); - fDebugRangesSection = fElfFile->GetSection(".debug_ranges"); - fDebugLineSection = fElfFile->GetSection(".debug_line"); - fDebugFrameSection = fElfFile->GetSection(".debug_frame"); + fDebugStringSection = debugInfoFile->GetSection(".debug_str"); + fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges"); + fDebugLineSection = debugInfoFile->GetSection(".debug_line"); + fDebugFrameSection = debugInfoFile->GetSection(".debug_frame"); + // .eh_frame doesn't appear to get copied into separate debug + // info files properly, therefore always use it off the main + // executable image fEHFrameSection = fElfFile->GetSection(".eh_frame"); - fDebugLocationSection = fElfFile->GetSection(".debug_loc"); - fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes"); + fDebugLocationSection = debugInfoFile->GetSection(".debug_loc"); + fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes"); // iterate through the debug info section DataReader dataReader(fDebugInfoSection->Data(), @@ -2224,3 +2259,107 @@ DwarfFile::_FindLocationExpression(CompilationUnit* unit, uint64 offset, } } } + + +status_t +DwarfFile::_LocateDebugInfo() +{ + ElfFile* debugInfoFile = fElfFile; + ElfSection* debugLinkSection = fElfFile->GetSection(".gnu_debuglink"); + if (debugLinkSection != NULL) { + AutoSectionPutter putter(fElfFile, debugLinkSection); + + // the file specifies a debug link, look at its target instead + // for debug information. + // Format: null-terminated filename, as many 0 padding bytes as + // needed to reach the next 32-bit address boundary, followed + // by a 32-bit CRC + + BString debugPath; + status_t result = _GetDebugInfoPath( + (const char*)debugLinkSection->Data(), debugPath); + if (result != B_OK) + return result; + + fAlternateName = strdup(debugPath.String()); + + if (fAlternateName == NULL) + return B_NO_MEMORY; + +/* + // TODO: validate CRC + int32 debugCRC = *(int32*)((char*)debugLinkSection->Data() + + debugLinkSection->Size() - sizeof(int32)); +*/ + fAlternateElfFile = new(std::nothrow) ElfFile; + if (fAlternateElfFile == NULL) + return B_NO_MEMORY; + + result = fAlternateElfFile->Init(fAlternateName); + if (result != B_OK) + return result; + + debugInfoFile = fAlternateElfFile; + } + + // get the interesting sections + fDebugInfoSection = debugInfoFile->GetSection(".debug_info"); + fDebugAbbrevSection = debugInfoFile->GetSection(".debug_abbrev"); + if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) { + WARNING("DwarfManager::File::Load(\"%s\"): no " + ".debug_info or .debug_abbrev.\n", fName); + return B_ERROR; + } + + return B_OK; +} + + +status_t +DwarfFile::_GetDebugInfoPath(const char* debugFileName, BString& _infoPath) +{ + const directory_which dirLocations[] = { B_USER_CONFIG_DIRECTORY, + B_COMMON_DIRECTORY, B_SYSTEM_DIRECTORY }; + + // first, see if we have a relative match to our local directory + BPath basePath; + status_t result = basePath.SetTo(fName); + if (result != B_OK) + return result; + basePath.GetParent(&basePath); + if (strcmp(basePath.Leaf(), "lib") == 0 || strcmp(basePath.Leaf(), + "add-ons") == 0) { + _infoPath.SetToFormat("%s/../debug/%s", basePath.Path(), + debugFileName); + } else + _infoPath.SetToFormat("%s/debug/%s", basePath.Path(), debugFileName); + + BEntry entry(_infoPath.String()); + result = entry.InitCheck(); + if (result != B_OK && result != B_ENTRY_NOT_FOUND) + return result; + if (entry.Exists()) + return B_OK; + + // See if our image is in any of the system locations. + // if so, look for its debug info in the corresponding location. + for (uint16 i = 0; i < sizeof(dirLocations) / sizeof(directory_which); + i++) { + result = find_directory(dirLocations[i], &basePath); + if (result != B_OK) + return result; + + if (strncmp(fName, basePath.Path(), strlen(basePath.Path())) == 0) { + _infoPath.SetToFormat("%s/develop/debug/%s", basePath.Path(), + debugFileName); + entry.SetTo(_infoPath.String()); + result = entry.InitCheck(); + if (result != B_OK && result != B_ENTRY_NOT_FOUND) + return result; + return entry.Exists() ? B_OK : B_ENTRY_NOT_FOUND; + } + } + + return B_ENTRY_NOT_FOUND; +} + diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h index b7d53b8351..ba08a08ddd 100644 --- a/src/apps/debugger/dwarf/DwarfFile.h +++ b/src/apps/debugger/dwarf/DwarfFile.h @@ -150,12 +150,18 @@ private: const void*& _expression, off_t& _length) const; + status_t _LocateDebugInfo(); + status_t _GetDebugInfoPath(const char* fileName, + BString& _infoPath); + private: friend class DwarfFile::ExpressionEvaluationContext; private: char* fName; + char* fAlternateName; ElfFile* fElfFile; + ElfFile* fAlternateElfFile; ElfSection* fDebugInfoSection; ElfSection* fDebugAbbrevSection; ElfSection* fDebugStringSection; |
