[haiku-commits] haiku: hrev44428 - src/apps/debugger/dwarf

  • From: anevilyak@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 29 Jul 2012 13:14:29 +0200 (CEST)

hrev44428 adds 1 changeset to branch 'master'
old head: 200dec066fdd9d18e8e93232a6e55e9f5ba3df30
new head: 224f75100b15ee71dce0b0e551efd40236ca8b54

----------------------------------------------------------------------------

224f751: Implement support for separate debug info files.
  
  - 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.

                                      [ Rene Gollent <anevilyak@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev44428
Commit:      224f75100b15ee71dce0b0e551efd40236ca8b54
URL:         http://cgit.haiku-os.org/haiku/commit/?id=224f751
Author:      Rene Gollent <anevilyak@xxxxxxxxx>
Date:        Sun Jul 29 11:07:04 2012 UTC

Ticket:      https://dev.haiku-os.org/ticket/8135

----------------------------------------------------------------------------

2 files changed, 167 insertions(+), 22 deletions(-)
src/apps/debugger/dwarf/DwarfFile.cpp |  183 +++++++++++++++++++++++++----
src/apps/debugger/dwarf/DwarfFile.h   |    6 +

----------------------------------------------------------------------------

diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp 
b/src/apps/debugger/dwarf/DwarfFile.cpp
index f95d18e..636b1fa 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 b7d53b8..ba08a08 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;


Other related posts:

  • » [haiku-commits] haiku: hrev44428 - src/apps/debugger/dwarf - anevilyak