@@ -19,6 +19,8 @@ import rt.backtrace.elf;
1919
2020import core.stdc.string : strlen, memchr;
2121
22+ // debug = DwarfDebugMachine;
23+
2224struct Location
2325{
2426 const (char )[] file = null ; // file is missing directory, but DMD emits directory directly into file
@@ -94,11 +96,14 @@ private:
9496// the lifetime of the Location data is the lifetime of the mmapped ElfSection
9597void resolveAddresses (ElfSection* debugLineSection, Location[] locations) @nogc nothrow
9698{
99+ debug (DwarfDebugMachine) import core.stdc.stdio ;
100+
97101 size_t numberOfLocationsFound = 0 ;
98102
99103 const (ubyte )[] dbg = debugLineSection.get ();
100104 while (dbg.length > 0 )
101105 {
106+ debug (DwarfDebugMachine) printf(" new debug program\n " );
102107 const (LPHeader)* lph = cast (const (LPHeader)* ) dbg.ptr;
103108
104109 if (lph.unitLength == 0xffff_ffff) // is 64-bit dwarf?
@@ -137,6 +142,7 @@ void resolveAddresses(ElfSection* debugLineSection, Location[] locations) @nogc
137142 while (pathData[0 ] != 0 )
138143 {
139144 directories[currentDirectoryIndex] = cast (const (char )[]) pathData[0 .. strlen(cast (char * ) (pathData.ptr))];
145+ debug (DwarfDebugMachine) printf(" dir: %s\n " , pathData.ptr);
140146 pathData = pathData[directories[currentDirectoryIndex].length + 1 .. $];
141147 currentDirectoryIndex++ ;
142148 }
@@ -165,6 +171,7 @@ void resolveAddresses(ElfSection* debugLineSection, Location[] locations) @nogc
165171 while (pathData[0 ] != 0 )
166172 {
167173 filenames[currentFileIndex] = cast (const (char )[]) pathData[0 .. strlen(cast (char * ) (pathData.ptr))];
174+ debug (DwarfDebugMachine) printf(" file: %s\n " , pathData.ptr);
168175 pathData = pathData[filenames[currentFileIndex].length + 1 .. $];
169176
170177 auto dirIndex = pathData.readULEB128(); // unused
@@ -177,27 +184,46 @@ void resolveAddresses(ElfSection* debugLineSection, Location[] locations) @nogc
177184 LocationInfo lastLoc = LocationInfo(- 1 , - 1 );
178185 size_t lastAddress = 0x0 ;
179186
187+ debug (DwarfDebugMachine) printf(" program:\n " );
180188 runStateMachine(lph, program, standardOpcodeLengths,
181- (size_t address, LocationInfo locInfo)
189+ (size_t address, LocationInfo locInfo, bool isEndSequence )
182190 {
183- foreach (ref loc; locations)
191+ // If loc.line != -1, then it has been set previously.
192+ // Some implementations (eg. dmd) write an address to
193+ // the debug data multiple times, but so far I have found
194+ // that the first occurrence to be the correct one.
195+ foreach (ref loc; locations) if (loc.line == - 1 )
184196 {
185197 if (loc.address == address)
186198 {
199+ debug (DwarfDebugMachine) printf(" -- found for [0x%x]:\n " , loc.address);
200+ debug (DwarfDebugMachine) printf(" -- file: %.*s\n " , filenames[locInfo.file - 1 ].length, filenames[locInfo.file - 1 ].ptr);
201+ debug (DwarfDebugMachine) printf(" -- line: %d\n " , locInfo.line);
187202 loc.file = filenames[locInfo.file - 1 ];
188203 loc.line = locInfo.line;
189204 numberOfLocationsFound++ ;
190205 }
191206 else if (loc.address < address && lastAddress < loc.address && lastAddress != 0 )
192207 {
208+ debug (DwarfDebugMachine) printf(" -- found for [0x%x]:\n " , loc.address);
209+ debug (DwarfDebugMachine) printf(" -- file: %.*s\n " , filenames[lastLoc.file - 1 ].length, filenames[lastLoc.file - 1 ].ptr);
210+ debug (DwarfDebugMachine) printf(" -- line: %d\n " , lastLoc.line);
193211 loc.file = filenames[lastLoc.file - 1 ];
194212 loc.line = lastLoc.line;
195213 numberOfLocationsFound++ ;
196214 }
197215 }
198216
199- lastAddress = address;
200- lastLoc = locInfo;
217+ if (isEndSequence)
218+ {
219+ lastAddress = 0 ;
220+ }
221+ else
222+ {
223+ lastAddress = address;
224+ lastLoc = locInfo;
225+ }
226+
201227 return numberOfLocationsFound < locations.length;
202228 }
203229 );
@@ -207,9 +233,11 @@ void resolveAddresses(ElfSection* debugLineSection, Location[] locations) @nogc
207233 }
208234}
209235
210- alias RunStateMachineCallback = bool delegate (size_t , LocationInfo) @nogc nothrow ;
236+ alias RunStateMachineCallback = bool delegate (size_t , LocationInfo, bool ) @nogc nothrow ;
211237bool runStateMachine (const (LPHeader)* lpHeader, const (ubyte )[] program, const (ubyte )[] standardOpcodeLengths, scope RunStateMachineCallback callback) @nogc nothrow
212238{
239+ debug (DwarfDebugMachine) import core.stdc.stdio ;
240+
213241 StateMachine machine;
214242 machine.isStatement = lpHeader.defaultIsStatement;
215243
@@ -228,98 +256,98 @@ bool runStateMachine(const(LPHeader)* lpHeader, const(ubyte)[] program, const(ub
228256 {
229257 case endSequence:
230258 machine.isEndSequence = true ;
231- // trace ("endSequence ", " 0x%x".format(m. address) );
232- if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line))) return true ;
259+ debug (DwarfDebugMachine) printf (" endSequence 0x%x\n " , machine. address);
260+ if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line), true )) return true ;
233261 machine = StateMachine.init;
234262 machine.isStatement = lpHeader.defaultIsStatement;
235263 break ;
236264
237265 case setAddress:
238266 size_t address = program.read! size_t ();
239- // trace ("setAddress ", " 0x%x".format( address) );
267+ debug (DwarfDebugMachine) printf (" setAddress 0x%x\n " , address);
240268 machine.address = address;
241269 break ;
242270
243271 case defineFile: // TODO: add proper implementation
244- // trace ("defineFile");
272+ debug (DwarfDebugMachine) printf (" defineFile\n " );
245273 program = program[len - 1 .. $];
246274 break ;
247275
248276 default :
249277 // unknown opcode
250- // trace ("unknown extended opcode ", eopcode);
278+ debug (DwarfDebugMachine) printf (" unknown extended opcode %d \n " , cast ( int ) eopcode);
251279 program = program[len - 1 .. $];
252280 break ;
253281 }
254282
255283 break ;
256284
257285 case copy:
258- // trace ("copy" );
259- if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line))) return true ;
286+ debug (DwarfDebugMachine) printf (" copy 0x%x \n " , machine.address );
287+ if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line), false )) return true ;
260288 machine.isBasicBlock = false ;
261289 machine.isPrologueEnd = false ;
262290 machine.isEpilogueBegin = false ;
263291 break ;
264292
265293 case advancePC:
266294 ulong op = readULEB128(program);
267- // trace("advancePC ", op * lpHeader.minimumInstructionLength);
268295 machine.address += op * lpHeader.minimumInstructionLength;
296+ debug (DwarfDebugMachine) printf(" advancePC %d to 0x%x\n " , cast (int ) (op * lpHeader.minimumInstructionLength), machine.address);
269297 break ;
270298
271299 case advanceLine:
272300 long ad = readSLEB128(program);
273- // trace("advanceLine ", ad);
274301 machine.line += ad;
302+ debug (DwarfDebugMachine) printf(" advanceLine %d to %d\n " , cast (int ) ad, cast (int ) machine.line);
275303 break ;
276304
277305 case setFile:
278306 uint index = cast (uint ) readULEB128(program);
279- // trace ("setFile to ", index);
307+ debug (DwarfDebugMachine) printf (" setFile to %d \n " , cast ( int ) index);
280308 machine.fileIndex = index;
281309 break ;
282310
283311 case setColumn:
284312 uint col = cast (uint ) readULEB128(program);
285- // trace ("setColumn ", col);
313+ debug (DwarfDebugMachine) printf (" setColumn %d \n " , cast ( int ) col);
286314 machine.column = col;
287315 break ;
288316
289317 case negateStatement:
290- // trace ("negateStatement");
318+ debug (DwarfDebugMachine) printf (" negateStatement\n " );
291319 machine.isStatement = ! machine.isStatement;
292320 break ;
293321
294322 case setBasicBlock:
295- // trace ("setBasicBlock");
323+ debug (DwarfDebugMachine) printf (" setBasicBlock\n " );
296324 machine.isBasicBlock = true ;
297325 break ;
298326
299327 case constAddPC:
300328 machine.address += (255 - lpHeader.opcodeBase) / lpHeader.lineRange * lpHeader.minimumInstructionLength;
301- // trace ("constAddPC ", " 0x%x".format( machine.address) );
329+ debug (DwarfDebugMachine) printf (" constAddPC 0x%x\n " , machine.address);
302330 break ;
303331
304332 case fixedAdvancePC:
305333 uint add = program.read! uint ();
306- // trace("fixedAdvancePC ", add);
307334 machine.address += add;
335+ debug (DwarfDebugMachine) printf(" fixedAdvancePC %d to 0x%x\n " , cast (int ) add, machine.address);
308336 break ;
309337
310338 case setPrologueEnd:
311339 machine.isPrologueEnd = true ;
312- // trace ("setPrologueEnd");
340+ debug (DwarfDebugMachine) printf (" setPrologueEnd\n " );
313341 break ;
314342
315343 case setEpilogueBegin:
316344 machine.isEpilogueBegin = true ;
317- // trace ("setEpilogueBegin");
345+ debug (DwarfDebugMachine) printf (" setEpilogueBegin\n " );
318346 break ;
319347
320348 case setISA:
321349 machine.isa = cast (uint ) readULEB128(program);
322- // trace ("setISA ", m .isa);
350+ debug (DwarfDebugMachine) printf (" setISA %d \n " , cast ( int ) machine .isa);
323351 break ;
324352
325353 default :
@@ -335,8 +363,8 @@ bool runStateMachine(const(LPHeader)* lpHeader, const(ubyte)[] program, const(ub
335363 auto linc = lpHeader.lineBase + (opcode % lpHeader.lineRange);
336364 machine.line += linc;
337365
338- // trace ("special ", ainc, " ", linc );
339- if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line))) return true ;
366+ debug (DwarfDebugMachine) printf (" special %d %d to 0x%x line %d \n " , cast ( int ) ainc, cast ( int ) linc, machine.address, cast ( int ) machine.line );
367+ if (! callback(machine.address, LocationInfo(machine.fileIndex, machine.line), false )) return true ;
340368 }
341369 }
342370
0 commit comments