View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0028283 | FPC | RTL | public | 2015-06-12 13:43 | 2019-05-02 14:23 |
Reporter | Denis Kozlov | Assigned To | Michael Van Canneyt | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Platform | Windows | ||||
Target Version | 3.0.2 | Fixed in Version | 3.1.1 | ||
Summary | 0028283: DWARF debug line info (lnfodwrf.pp) is broken | ||||
Description | This is a follow up from a recently fixed STABS bug (lineinfo.pp): http://bugs.freepascal.org/view.php?id=13518 DWARF debug line info (lnfodwrf.pp) seems to be broken in several ways. 1) The static "dwarferr" variable disables the whole unit on the first failure to read debug exe section, e.g. when address results in an external library which doesn't have debug info. Same type of issue as in the recently closed STABS bug. 2) The back trace only produces line info for the first address (without function name), and nothing for the rest of lines. This is even if the above problem is fixed. Attached below in Additional Information section is a comparison of back traces between DWARF (lnfodwrf.pp) and fixed STABS (lineinfo.pp). Project was tested with several debug info types, i.e.: Dwarf with sets, Dwarf2, Dwarf3, Stabs. Using a slightly modified version of the example project from above mentioned STABS bug. | ||||
Additional Information | Back trace using DWARF: =========================================================== $00423E0A line 78 of unit1.pas $00504D4E $0051C1FF $0051C8FF $0051C11A $0040AE26 $004F8DFE $00542275 $004D1E2A $00547B25 $75B76238 $75B768EA $75B7CD1A $75B7CD81 $70E44601 $70E44663 $70E444ED =========================================================== Back trace using STABS: =========================================================== $00423E0A TFORM1__BUTTON2CLICK, line 78 of unit1.pas $00504D4E TCONTROL__CLICK, line 2711 of ./include/control.inc $0051C1FF TBUTTONCONTROL__CLICK, line 54 of ./include/buttoncontrol.inc $0051C8FF TCUSTOMBUTTON__CLICK, line 169 of ./include/buttons.inc $0051C11A TBUTTONCONTROL__WMDEFAULTCLICKED, line 20 of ./include/buttoncontrol.inc $0040AE26 $004F8DFE TWINCONTROL__WNDPROC, line 5326 of ./include/wincontrol.inc $00542275 DELIVERMESSAGE, line 112 of lclmessageglue.pas $004D1E2A WINDOWPROC, line 2480 of ./win32/win32callback.inc $00547B25 CUSTOMFORMWNDPROC, line 395 of ./win32/win32wsforms.pp $75B76238 $75B768EA $75B7CD1A $75B7CD81 $70E44601 $70E44663 $70E444ED =========================================================== | ||||
Tags | BackTraceStrFunc, DwarfBackTraceStr, Exception, lnfodwrf, patch | ||||
Fixed in Revision | 32919 | ||||
FPCOldBugId | |||||
FPCTarget | |||||
Attached Files |
|
|
|
|
Attached a sample project. Currently debug info type is set to Dwarf2, but can be changed in Project Options if needed. |
|
Please don't submit lazarus projects when reporting FPC bugs. |
|
http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information states that debug_info must be read for the function names; but only debug_lines is read in lnfodwrf. |
|
|
|
Uploaded a simple program that shows the missing function names. (does not show the error in case of missing debug info) |
|
That the function names are missing is known, it's simply not implemented. See e.g. 0017547 I'm not aware of any bug reports about the DWARF lineinfo unit only showing something for the first entry in the backtrace though. |
|
I am not sure about that either, but it is correct that it stops as soon as there is a module (lib) without debug info, the design was the same as for the old lineinfo unit. That part can probably easily be copied. |
|
20160109-lnfodwrf.pp.patch (5,436 bytes)
Index: rtl/inc/lnfodwrf.pp =================================================================== --- rtl/inc/lnfodwrf.pp (revision 32893) +++ rtl/inc/lnfodwrf.pp (working copy) @@ -21,12 +21,28 @@ dependent on objpas unit. } unit lnfodwrf; + interface {$S-} +{$IF FPC_VERSION<3} +type + CodePointer = Pointer; +{$ENDIF} + function GetLineInfo(addr:ptruint;var func,source:string;var line:longint) : boolean; +function DwarfBackTraceStr(addr: CodePointer): string; +procedure CloseDwarf; +var + // Allows more efficient operation by reusing previously loaded debug data + // when the target module filename is the same. However, if an invalid memory + // address is supplied then further calls may result in an undefined behaviour. + // In summary: enable for speed, disable for resilience. + AllowReuseOfLineInfoData: Boolean = True; + + implementation uses @@ -61,7 +77,6 @@ e : TExeFile; EBuf: Array [0..EBUF_SIZE-1] of Byte; EBufCnt, EBufPos: Integer; - DwarfErr : boolean; { the offset and size of the DWARF debug_line section in the file } DwarfOffset : longint; DwarfSize : longint; @@ -137,18 +152,47 @@ baseaddr : pointer; filename, dbgfn : string; + lastfilename: string; { store last processed file } + lastopendwarf: Boolean; { store last result of processing a file } -function Opendwarf(addr : pointer) : boolean; +function OpenDwarf(addr : pointer) : boolean; begin - Opendwarf:=false; - if dwarferr then - exit; + // False by default + Result:=false; + // Empty so can test if GetModuleByAddr has worked + filename := ''; + + // Get filename by address using GetModuleByAddr GetModuleByAddr(addr,baseaddr,filename); {$ifdef DEBUG_LINEINFO} writeln(stderr,filename,' Baseaddr: ',hexstr(ptruint(baseaddr),sizeof(baseaddr)*2)); {$endif DEBUG_LINEINFO} + // Check if GetModuleByAddr has worked + if filename = '' then + exit; + + // If target filename same as previous, then re-use previous result + if AllowReuseOfLineInfoData and (filename = lastfilename) then + begin + {$ifdef DEBUG_LINEINFO} + writeln(stderr,'Reusing debug data'); + {$endif DEBUG_LINEINFO} + Result:=lastopendwarf; + exit; + end; + + // Close previously opened stabs + CloseDwarf; + + // Reset last open stabs result + lastopendwarf := false; + + // Save newly processed filename + lastfilename := filename; + + // Open exe file or debug link if not OpenExeFile(e,filename) then exit; if ReadDebugLink(e,dbgfn) then @@ -158,21 +202,25 @@ exit; end; + // Find debug data section e.processaddress:=ptruint(baseaddr)-e.processaddress; - if FindExeSection(e,'.debug_line',dwarfoffset,dwarfsize) then - Opendwarf:=true + begin + lastopendwarf:=true; + Result:=true; + end else - begin - dwarferr:=true; - exit; - end; + CloseExeFile(e); end; -procedure Closedwarf; +procedure CloseDwarf; begin - CloseExeFile(e); + if e.isopen then + CloseExeFile(e); + + // Reset last processed filename + lastfilename := ''; end; @@ -730,14 +778,10 @@ func := ''; source := ''; found := false; - GetLineInfo:=false; - if DwarfErr then + Result:=false; + + if not OpenDwarf(pointer(addr)) then exit; - if not e.isopen then - begin - if not OpenDwarf(pointer(addr)) then - exit; - end; addr := addr - e.processaddress; @@ -749,21 +793,26 @@ current_offset := ParseCompilationUnit(addr, current_offset, source, line, found); end; - if e.isopen then + + if not AllowReuseOfLineInfoData then CloseDwarf; - GetLineInfo:=true; + + Result:=true; end; -function DwarfBackTraceStr(addr : CodePointer) : shortstring; +function DwarfBackTraceStr(addr: CodePointer): string; var func, source : string; - hs : string[32]; + hs : string; line : longint; Store : TBackTraceStrFunc; Success : boolean; begin + {$ifdef DEBUG_LINEINFO} + writeln(stderr,'DwarfBackTraceStr called'); + {$endif DEBUG_LINEINFO} { reset to prevent infinite recursion if problems inside the code } Success:=false; Store := BackTraceStrFunc; @@ -770,28 +819,33 @@ BackTraceStrFunc := @SysBackTraceStr; Success:=GetLineInfo(ptruint(addr), func, source, line); { create string } - DwarfBackTraceStr :=' $' + HexStr(ptruint(addr), sizeof(ptruint) * 2); - if func<>'' then - DwarfBackTraceStr := DwarfBackTraceStr + ' ' + func; - - if source<>'' then begin + Result :=' $' + HexStr(ptruint(addr), sizeof(ptruint) * 2); + if Success then + begin if func<>'' then - DwarfBackTraceStr := DwarfBackTraceStr + ', '; - if line<>0 then begin - str(line, hs); - DwarfBackTraceStr := DwarfBackTraceStr + ' line ' + hs; + Result := Result + ' ' + func; + if source<>'' then + begin + if func<>'' then + Result := Result + ', '; + if line<>0 then + begin + str(line, hs); + Result := Result + ' line ' + hs; + end; + Result := Result + ' of ' + source; end; - DwarfBackTraceStr := DwarfBackTraceStr + ' of ' + source; end; - if Success then - BackTraceStrFunc := Store; + BackTraceStrFunc := Store; end; initialization + lastfilename := ''; + lastopendwarf := false; BackTraceStrFunc := @DwarfBacktraceStr; finalization - if e.isopen then - CloseDwarf(); + CloseDwarf; + end. |
|
Attached patch fixes issues as discussed on the mailing list: http://lists.freepascal.org/pipermail/fpc-devel/2016-January/036462.html 20160109-2-lnfodwrf.pp.patch [^] (5,377 bytes) 2016-01-09 13:58 Summary of changes: 1) Apply fixes from STABS to DWARF - fix permanently disabled line info when a module without line info is encountered. 2) Optional reuse of line info data via global AllowReuseOfLineInfoData variable. 3) Minor code clean up. |
|
20160109-2-lnfodwrf.pp.patch (5,377 bytes)
Index: rtl/inc/lnfodwrf.pp =================================================================== --- rtl/inc/lnfodwrf.pp (revision 32893) +++ rtl/inc/lnfodwrf.pp (working copy) @@ -21,12 +21,28 @@ dependent on objpas unit. } unit lnfodwrf; + interface {$S-} +{$IF FPC_VERSION<3} +type + CodePointer = Pointer; +{$ENDIF} + function GetLineInfo(addr:ptruint;var func,source:string;var line:longint) : boolean; +function DwarfBackTraceStr(addr: CodePointer): string; +procedure CloseDwarf; +var + // Allows more efficient operation by reusing previously loaded debug data + // when the target module filename is the same. However, if an invalid memory + // address is supplied then further calls may result in an undefined behaviour. + // In summary: enable for speed, disable for resilience. + AllowReuseOfLineInfoData: Boolean = True; + + implementation uses @@ -61,7 +77,6 @@ e : TExeFile; EBuf: Array [0..EBUF_SIZE-1] of Byte; EBufCnt, EBufPos: Integer; - DwarfErr : boolean; { the offset and size of the DWARF debug_line section in the file } DwarfOffset : longint; DwarfSize : longint; @@ -137,18 +152,47 @@ baseaddr : pointer; filename, dbgfn : string; + lastfilename: string; { store last processed file } + lastopendwarf: Boolean; { store last result of processing a file } -function Opendwarf(addr : pointer) : boolean; +function OpenDwarf(addr : pointer) : boolean; begin - Opendwarf:=false; - if dwarferr then - exit; + // False by default + OpenDwarf:=false; + // Empty so can test if GetModuleByAddr has worked + filename := ''; + + // Get filename by address using GetModuleByAddr GetModuleByAddr(addr,baseaddr,filename); {$ifdef DEBUG_LINEINFO} writeln(stderr,filename,' Baseaddr: ',hexstr(ptruint(baseaddr),sizeof(baseaddr)*2)); {$endif DEBUG_LINEINFO} + // Check if GetModuleByAddr has worked + if filename = '' then + exit; + + // If target filename same as previous, then re-use previous result + if AllowReuseOfLineInfoData and (filename = lastfilename) then + begin + {$ifdef DEBUG_LINEINFO} + writeln(stderr,'Reusing debug data'); + {$endif DEBUG_LINEINFO} + OpenDwarf:=lastopendwarf; + exit; + end; + + // Close previously opened stabs + CloseDwarf; + + // Reset last open stabs result + lastopendwarf := false; + + // Save newly processed filename + lastfilename := filename; + + // Open exe file or debug link if not OpenExeFile(e,filename) then exit; if ReadDebugLink(e,dbgfn) then @@ -158,21 +202,25 @@ exit; end; + // Find debug data section e.processaddress:=ptruint(baseaddr)-e.processaddress; - if FindExeSection(e,'.debug_line',dwarfoffset,dwarfsize) then - Opendwarf:=true + begin + lastopendwarf:=true; + OpenDwarf:=true; + end else - begin - dwarferr:=true; - exit; - end; + CloseExeFile(e); end; -procedure Closedwarf; +procedure CloseDwarf; begin - CloseExeFile(e); + if e.isopen then + CloseExeFile(e); + + // Reset last processed filename + lastfilename := ''; end; @@ -731,13 +779,9 @@ source := ''; found := false; GetLineInfo:=false; - if DwarfErr then + + if not OpenDwarf(pointer(addr)) then exit; - if not e.isopen then - begin - if not OpenDwarf(pointer(addr)) then - exit; - end; addr := addr - e.processaddress; @@ -749,21 +793,26 @@ current_offset := ParseCompilationUnit(addr, current_offset, source, line, found); end; - if e.isopen then + + if not AllowReuseOfLineInfoData then CloseDwarf; + GetLineInfo:=true; end; -function DwarfBackTraceStr(addr : CodePointer) : shortstring; +function DwarfBackTraceStr(addr: CodePointer): string; var func, source : string; - hs : string[32]; + hs : string; line : longint; Store : TBackTraceStrFunc; Success : boolean; begin + {$ifdef DEBUG_LINEINFO} + writeln(stderr,'DwarfBackTraceStr called'); + {$endif DEBUG_LINEINFO} { reset to prevent infinite recursion if problems inside the code } Success:=false; Store := BackTraceStrFunc; @@ -771,27 +820,32 @@ Success:=GetLineInfo(ptruint(addr), func, source, line); { create string } DwarfBackTraceStr :=' $' + HexStr(ptruint(addr), sizeof(ptruint) * 2); - if func<>'' then - DwarfBackTraceStr := DwarfBackTraceStr + ' ' + func; - - if source<>'' then begin + if Success then + begin if func<>'' then - DwarfBackTraceStr := DwarfBackTraceStr + ', '; - if line<>0 then begin - str(line, hs); - DwarfBackTraceStr := DwarfBackTraceStr + ' line ' + hs; + DwarfBackTraceStr := DwarfBackTraceStr + ' ' + func; + if source<>'' then + begin + if func<>'' then + DwarfBackTraceStr := DwarfBackTraceStr + ', '; + if line<>0 then + begin + str(line, hs); + DwarfBackTraceStr := DwarfBackTraceStr + ' line ' + hs; + end; + DwarfBackTraceStr := DwarfBackTraceStr + ' of ' + source; end; - DwarfBackTraceStr := DwarfBackTraceStr + ' of ' + source; end; - if Success then - BackTraceStrFunc := Store; + BackTraceStrFunc := Store; end; initialization + lastfilename := ''; + lastopendwarf := false; BackTraceStrFunc := @DwarfBacktraceStr; finalization - if e.isopen then - CloseDwarf(); + CloseDwarf; + end. |
|
Applied the patch. Thank you! |
Date Modified | Username | Field | Change |
---|---|---|---|
2015-06-12 13:43 | Denis Kozlov | New Issue | |
2015-06-12 13:44 | Denis Kozlov | Tag Attached: BackTraceStrFunc | |
2015-06-12 13:44 | Denis Kozlov | Tag Attached: Exception | |
2015-06-12 13:44 | Denis Kozlov | Tag Attached: DwarfBackTraceStr | |
2015-06-12 13:44 | Denis Kozlov | Tag Attached: lnfodwrf | |
2015-06-12 13:50 | Denis Kozlov | File Added: example-application-on-exception-line-info-dwarf.zip | |
2015-06-12 13:52 | Denis Kozlov | Note Added: 0084398 | |
2015-06-12 16:18 | Jonas Maebe | Note Added: 0084407 | |
2015-06-12 18:12 | Michael Van Canneyt | Note Added: 0084413 | |
2015-06-12 18:13 | Michael Van Canneyt | File Added: simple_no_functionnames.zip | |
2015-06-12 18:13 | Michael Van Canneyt | Note Added: 0084414 | |
2015-06-12 18:18 | Jonas Maebe | Note Added: 0084415 | |
2015-06-12 20:14 | Michael Van Canneyt | Relationship added | related to 0017547 |
2015-06-12 20:16 | Michael Van Canneyt | Note Added: 0084420 | |
2016-01-09 12:30 | Denis Kozlov | File Added: 20160109-lnfodwrf.pp.patch | |
2016-01-09 12:30 | Denis Kozlov | Note Added: 0088738 | |
2016-01-09 12:36 | Denis Kozlov | Tag Attached: patch | |
2016-01-09 14:58 | Denis Kozlov | File Added: 20160109-2-lnfodwrf.pp.patch | |
2016-01-09 14:59 | Denis Kozlov | Note Edited: 0088738 | View Revisions |
2016-01-10 21:15 | Michael Van Canneyt | Fixed in Revision | => 32919 |
2016-01-10 21:15 | Michael Van Canneyt | Note Added: 0088764 | |
2016-01-10 21:15 | Michael Van Canneyt | Status | new => resolved |
2016-01-10 21:15 | Michael Van Canneyt | Fixed in Version | => 3.1.1 |
2016-01-10 21:15 | Michael Van Canneyt | Resolution | open => fixed |
2016-01-10 21:15 | Michael Van Canneyt | Assigned To | => Michael Van Canneyt |
2016-01-10 21:15 | Michael Van Canneyt | Target Version | => 3.0.2 |