Ticket #8135: debugger.external_debug_info.patch.2

File debugger.external_debug_info.patch.2, 7.6 KB (added by anevilyak, 12 years ago)
Line 
1diff --git a/src/apps/debugger/dwarf/DwarfFile.cpp b/src/apps/debugger/dwarf/DwarfFile.cpp
2index f95d18e..2224f62 100644
3--- a/src/apps/debugger/dwarf/DwarfFile.cpp
4+++ b/src/apps/debugger/dwarf/DwarfFile.cpp
5@@ -11,6 +11,9 @@
6 #include <new>
7
8 #include <AutoDeleter.h>
9+#include <Entry.h>
10+#include <FindDirectory.h>
11+#include <Path.h>
12
13 #include "AttributeClasses.h"
14 #include "AttributeValue.h"
15@@ -27,6 +30,30 @@
16 #include "Variant.h"
17
18
19+// #pragma mark - AutoSectionPutter
20+
21+
22+class AutoSectionPutter {
23+public:
24+ AutoSectionPutter(ElfFile* elfFile, ElfSection* elfSection)
25+ :
26+ fElfFile(elfFile),
27+ fElfSection(elfSection)
28+ {
29+ }
30+
31+ ~AutoSectionPutter()
32+ {
33+ if (fElfSection != NULL)
34+ fElfFile->PutSection(fElfSection);
35+ }
36+
37+private:
38+ ElfFile* fElfFile;
39+ ElfSection* fElfSection;
40+};
41+
42+
43 // #pragma mark - ExpressionEvaluationContext
44
45
46@@ -281,7 +308,9 @@ private:
47 DwarfFile::DwarfFile()
48 :
49 fName(NULL),
50+ fAlternateName(NULL),
51 fElfFile(NULL),
52+ fAlternateElfFile(NULL),
53 fDebugInfoSection(NULL),
54 fDebugAbbrevSection(NULL),
55 fDebugStringSection(NULL),
56@@ -305,19 +334,24 @@ DwarfFile::~DwarfFile()
57 delete table;
58
59 if (fElfFile != NULL) {
60- fElfFile->PutSection(fDebugInfoSection);
61- fElfFile->PutSection(fDebugAbbrevSection);
62- fElfFile->PutSection(fDebugStringSection);
63- fElfFile->PutSection(fDebugRangesSection);
64- fElfFile->PutSection(fDebugLineSection);
65- fElfFile->PutSection(fDebugFrameSection);
66+ ElfFile* debugInfoFile = fAlternateElfFile != NULL
67+ ? fAlternateElfFile : fElfFile;
68+
69+ debugInfoFile->PutSection(fDebugInfoSection);
70+ debugInfoFile->PutSection(fDebugAbbrevSection);
71+ debugInfoFile->PutSection(fDebugStringSection);
72+ debugInfoFile->PutSection(fDebugRangesSection);
73+ debugInfoFile->PutSection(fDebugLineSection);
74+ debugInfoFile->PutSection(fDebugFrameSection);
75 fElfFile->PutSection(fEHFrameSection);
76- fElfFile->PutSection(fDebugLocationSection);
77- fElfFile->PutSection(fDebugPublicTypesSection);
78+ debugInfoFile->PutSection(fDebugLocationSection);
79+ debugInfoFile->PutSection(fDebugPublicTypesSection);
80 delete fElfFile;
81+ delete fAlternateElfFile;
82 }
83
84 free(fName);
85+ free(fAlternateName);
86 }
87
88
89@@ -337,23 +371,24 @@ DwarfFile::Load(const char* fileName)
90 if (error != B_OK)
91 return error;
92
93- // get the interesting sections
94- fDebugInfoSection = fElfFile->GetSection(".debug_info");
95- fDebugAbbrevSection = fElfFile->GetSection(".debug_abbrev");
96- if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
97- WARNING("DwarfManager::File::Load(\"%s\"): no "
98- ".debug_info or .debug_abbrev.\n", fileName);
99- return B_ERROR;
100- }
101+ error = _LocateDebugInfo();
102+ if (error != B_OK)
103+ return error;
104+
105+ ElfFile* debugInfoFile = fAlternateElfFile != NULL
106+ ? fAlternateElfFile : fElfFile;
107
108 // non mandatory sections
109- fDebugStringSection = fElfFile->GetSection(".debug_str");
110- fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
111- fDebugLineSection = fElfFile->GetSection(".debug_line");
112- fDebugFrameSection = fElfFile->GetSection(".debug_frame");
113+ fDebugStringSection = debugInfoFile->GetSection(".debug_str");
114+ fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges");
115+ fDebugLineSection = debugInfoFile->GetSection(".debug_line");
116+ fDebugFrameSection = debugInfoFile->GetSection(".debug_frame");
117+ // .eh_frame doesn't appear to get copied into separate debug
118+ // info files properly, therefore always use it off the main
119+ // executable image
120 fEHFrameSection = fElfFile->GetSection(".eh_frame");
121- fDebugLocationSection = fElfFile->GetSection(".debug_loc");
122- fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
123+ fDebugLocationSection = debugInfoFile->GetSection(".debug_loc");
124+ fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes");
125
126 // iterate through the debug info section
127 DataReader dataReader(fDebugInfoSection->Data(),
128@@ -2224,3 +2259,106 @@ DwarfFile::_FindLocationExpression(CompilationUnit* unit, uint64 offset,
129 }
130 }
131 }
132+
133+
134+status_t
135+DwarfFile::_LocateDebugInfo()
136+{
137+ ElfFile* debugInfoFile = fElfFile;
138+ ElfSection* debugLinkSection = fElfFile->GetSection(".gnu_debuglink");
139+ if (debugLinkSection != NULL) {
140+ AutoSectionPutter putter(fElfFile, debugLinkSection);
141+
142+ // the file specifies a debug link, look at its target instead
143+ // for debug information.
144+ // Format: null-terminated filename, as many 0 padding bytes as
145+ // needed to reach the next 32-bit address boundary, followed
146+ // by a 32-bit CRC
147+
148+ BString debugPath;
149+ status_t result = _GetDebugInfoPath(debugPath,
150+ (const char*)debugLinkSection->Data());
151+ if (result != B_OK)
152+ return result;
153+
154+ fAlternateName = strdup(debugPath.String());
155+
156+ if (fAlternateName == NULL)
157+ return B_NO_MEMORY;
158+
159+/*
160+ // TODO: validate CRC
161+ int32 debugCRC = *(int32*)((char*)debugLinkSection->Data()
162+ + debugLinkSection->Size() - sizeof(int32));
163+*/
164+ fAlternateElfFile = new(std::nothrow) ElfFile;
165+ if (fAlternateElfFile == NULL)
166+ return B_NO_MEMORY;
167+
168+ result = fAlternateElfFile->Init(fAlternateName);
169+ if (result != B_OK)
170+ return result;
171+
172+ debugInfoFile = fAlternateElfFile;
173+ }
174+
175+ // get the interesting sections
176+ fDebugInfoSection = debugInfoFile->GetSection(".debug_info");
177+ fDebugAbbrevSection = debugInfoFile->GetSection(".debug_abbrev");
178+ if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
179+ WARNING("DwarfManager::File::Load(\"%s\"): no "
180+ ".debug_info or .debug_abbrev.\n", fName);
181+ return B_ERROR;
182+ }
183+
184+ return B_OK;
185+}
186+
187+
188+status_t
189+DwarfFile::_GetDebugInfoPath(BString& _infoPath, const char* debugFileName)
190+{
191+ int16 dirLocations[] = { B_SYSTEM_DIRECTORY, B_COMMON_DIRECTORY,
192+ B_USER_CONFIG_DIRECTORY, -1 };
193+
194+ // first, see if we have a relative match to our local directory
195+ BPath basePath;
196+ status_t result = basePath.SetTo(fName);
197+ if (result != B_OK)
198+ return result;
199+ basePath.GetParent(&basePath);
200+ if (strcmp(basePath.Leaf(), "lib") == 0 || strcmp(basePath.Leaf(),
201+ "add-ons") == 0) {
202+ _infoPath.SetToFormat("%s/../debug/%s", basePath.Path(),
203+ debugFileName);
204+ } else
205+ _infoPath.SetToFormat("%s/debug/%s", basePath.Path(), debugFileName);
206+
207+ BEntry entry(_infoPath.String());
208+ result = entry.InitCheck();
209+ if (result != B_OK && result != B_ENTRY_NOT_FOUND)
210+ return result;
211+ if (entry.Exists())
212+ return B_OK;
213+
214+ // See if our image is in any of the system locations.
215+ // if so, look for its debug info in the corresponding location.
216+ for (int16 i = 0; dirLocations[i] >= 0; i++) {
217+ result = find_directory((directory_which)dirLocations[i], &basePath);
218+ if (result != B_OK)
219+ return result;
220+
221+ if (strncmp(fName, basePath.Path(), strlen(basePath.Path())) == 0) {
222+ _infoPath.SetToFormat("%s/develop/debug/%s", basePath.Path(),
223+ debugFileName);
224+ entry.SetTo(_infoPath.String());
225+ result = entry.InitCheck();
226+ if (result != B_OK && result != B_ENTRY_NOT_FOUND)
227+ return result;
228+ return entry.Exists() ? B_OK : B_ENTRY_NOT_FOUND;
229+ }
230+ }
231+
232+ return B_ENTRY_NOT_FOUND;
233+}
234+
235diff --git a/src/apps/debugger/dwarf/DwarfFile.h b/src/apps/debugger/dwarf/DwarfFile.h
236index b7d53b8..e060469 100644
237--- a/src/apps/debugger/dwarf/DwarfFile.h
238+++ b/src/apps/debugger/dwarf/DwarfFile.h
239@@ -150,12 +150,18 @@ private:
240 const void*& _expression,
241 off_t& _length) const;
242
243+ status_t _LocateDebugInfo();
244+ status_t _GetDebugInfoPath(BString& _infoPath,
245+ const char* fileName);
246+
247 private:
248 friend class DwarfFile::ExpressionEvaluationContext;
249
250 private:
251 char* fName;
252+ char* fAlternateName;
253 ElfFile* fElfFile;
254+ ElfFile* fAlternateElfFile;
255 ElfSection* fDebugInfoSection;
256 ElfSection* fDebugAbbrevSection;
257 ElfSection* fDebugStringSection;