* Fix for bug ID #28283 by Denis Kozlov

git-svn-id: trunk@32919 -
This commit is contained in:
michael 2016-01-10 20:14:28 +00:00
parent 5e9c34ff47
commit 9225ff3293

View File

@ -21,11 +21,27 @@
dependent on objpas unit. dependent on objpas unit.
} }
unit lnfodwrf; unit lnfodwrf;
interface interface
{$S-} {$S-}
{$IF FPC_VERSION<3}
type
CodePointer = Pointer;
{$ENDIF}
function GetLineInfo(addr:ptruint;var func,source:string;var line:longint) : boolean; 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 implementation
@ -61,7 +77,6 @@ var
e : TExeFile; e : TExeFile;
EBuf: Array [0..EBUF_SIZE-1] of Byte; EBuf: Array [0..EBUF_SIZE-1] of Byte;
EBufCnt, EBufPos: Integer; EBufCnt, EBufPos: Integer;
DwarfErr : boolean;
{ the offset and size of the DWARF debug_line section in the file } { the offset and size of the DWARF debug_line section in the file }
DwarfOffset : longint; DwarfOffset : longint;
DwarfSize : longint; DwarfSize : longint;
@ -137,18 +152,47 @@ var
baseaddr : pointer; baseaddr : pointer;
filename, filename,
dbgfn : string; 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 begin
Opendwarf:=false; // False by default
if dwarferr then OpenDwarf:=false;
exit;
// Empty so can test if GetModuleByAddr has worked
filename := '';
// Get filename by address using GetModuleByAddr
GetModuleByAddr(addr,baseaddr,filename); GetModuleByAddr(addr,baseaddr,filename);
{$ifdef DEBUG_LINEINFO} {$ifdef DEBUG_LINEINFO}
writeln(stderr,filename,' Baseaddr: ',hexstr(ptruint(baseaddr),sizeof(baseaddr)*2)); writeln(stderr,filename,' Baseaddr: ',hexstr(ptruint(baseaddr),sizeof(baseaddr)*2));
{$endif DEBUG_LINEINFO} {$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 Dwarf
CloseDwarf;
// Reset last open dwarf result
lastopendwarf := false;
// Save newly processed filename
lastfilename := filename;
// Open exe file or debug link
if not OpenExeFile(e,filename) then if not OpenExeFile(e,filename) then
exit; exit;
if ReadDebugLink(e,dbgfn) then if ReadDebugLink(e,dbgfn) then
@ -158,21 +202,25 @@ begin
exit; exit;
end; end;
// Find debug data section
e.processaddress:=ptruint(baseaddr)-e.processaddress; e.processaddress:=ptruint(baseaddr)-e.processaddress;
if FindExeSection(e,'.debug_line',dwarfoffset,dwarfsize) then if FindExeSection(e,'.debug_line',dwarfoffset,dwarfsize) then
Opendwarf:=true begin
lastopendwarf:=true;
OpenDwarf:=true;
end
else else
begin CloseExeFile(e);
dwarferr:=true;
exit;
end;
end; end;
procedure Closedwarf; procedure CloseDwarf;
begin begin
CloseExeFile(e); if e.isopen then
CloseExeFile(e);
// Reset last processed filename
lastfilename := '';
end; end;
@ -731,13 +779,9 @@ begin
source := ''; source := '';
found := false; found := false;
GetLineInfo:=false; GetLineInfo:=false;
if DwarfErr then
if not OpenDwarf(pointer(addr)) then
exit; exit;
if not e.isopen then
begin
if not OpenDwarf(pointer(addr)) then
exit;
end;
addr := addr - e.processaddress; addr := addr - e.processaddress;
@ -749,21 +793,26 @@ begin
current_offset := ParseCompilationUnit(addr, current_offset, current_offset := ParseCompilationUnit(addr, current_offset,
source, line, found); source, line, found);
end; end;
if e.isopen then
if not AllowReuseOfLineInfoData then
CloseDwarf; CloseDwarf;
GetLineInfo:=true; GetLineInfo:=true;
end; end;
function DwarfBackTraceStr(addr : CodePointer) : shortstring; function DwarfBackTraceStr(addr: CodePointer): string;
var var
func, func,
source : string; source : string;
hs : string[32]; hs : string;
line : longint; line : longint;
Store : TBackTraceStrFunc; Store : TBackTraceStrFunc;
Success : boolean; Success : boolean;
begin begin
{$ifdef DEBUG_LINEINFO}
writeln(stderr,'DwarfBackTraceStr called');
{$endif DEBUG_LINEINFO}
{ reset to prevent infinite recursion if problems inside the code } { reset to prevent infinite recursion if problems inside the code }
Success:=false; Success:=false;
Store := BackTraceStrFunc; Store := BackTraceStrFunc;
@ -771,27 +820,32 @@ begin
Success:=GetLineInfo(ptruint(addr), func, source, line); Success:=GetLineInfo(ptruint(addr), func, source, line);
{ create string } { create string }
DwarfBackTraceStr :=' $' + HexStr(ptruint(addr), sizeof(ptruint) * 2); DwarfBackTraceStr :=' $' + HexStr(ptruint(addr), sizeof(ptruint) * 2);
if func<>'' then
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;
if Success then if Success then
BackTraceStrFunc := Store; begin
if func<>'' then
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;
end;
BackTraceStrFunc := Store;
end; end;
initialization initialization
lastfilename := '';
lastopendwarf := false;
BackTraceStrFunc := @DwarfBacktraceStr; BackTraceStrFunc := @DwarfBacktraceStr;
finalization finalization
if e.isopen then CloseDwarf;
CloseDwarf();
end. end.