mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-13 07:49:25 +02:00
+ added dwarfloading to windebugger
git-svn-id: trunk@10056 -
This commit is contained in:
parent
53cc3f202c
commit
13f2d243a5
@ -36,14 +36,14 @@ unit FPWDCommand;
|
||||
interface
|
||||
|
||||
uses
|
||||
SysUtils, Classes, Windows, WinDebugger, WinDExtra, LCLProc;
|
||||
SysUtils, Classes, Windows, WinDExtra, LCLProc;
|
||||
|
||||
procedure HandleCommand(ACommand: String);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
FPWDGlobal, FPWDLoop, FPWDPEImage, FPWDType;
|
||||
FPWDGlobal, FPWDLoop, FPWDPEImage;
|
||||
|
||||
type
|
||||
TMWDCommandHandler = procedure(AParams: String);
|
||||
@ -170,7 +170,7 @@ begin
|
||||
ZeroMemory(@ProcessInformation, SizeOf(ProcessInformation));
|
||||
if not CreateProcess(nil, PChar(GFileName), nil, nil, True, DETACHED_PROCESS or DEBUG_PROCESS or CREATE_NEW_PROCESS_GROUP, nil, nil, StartUpInfo, ProcessInformation)
|
||||
then begin
|
||||
WriteLN('Create process failed');
|
||||
WriteLN('Create process failed: ', GetLastErrorText);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
@ -185,7 +185,6 @@ var
|
||||
begin
|
||||
WriteLN('Base adress: ', FormatAddress(AEvent.LoadDll.lpBaseOfDll));
|
||||
|
||||
|
||||
if GetProcess(AEvent.dwProcessId, Proc)
|
||||
and Proc.GetLib(AEvent.LoadDll.hFile, Lib)
|
||||
then begin
|
||||
@ -330,6 +329,35 @@ procedure DebugLoop;
|
||||
{$endif}
|
||||
WriteLN(' ', CodeBytes, ' ', Code);
|
||||
end;
|
||||
|
||||
procedure ShowCode;
|
||||
var
|
||||
a: TDbgPtr;
|
||||
sym, symproc: TDbgSymbol;
|
||||
begin
|
||||
WriteLN('===');
|
||||
{$ifdef cpui386}
|
||||
a := GCurrentContext^.EIP;
|
||||
{$else}
|
||||
a := GCurrentContext^.RIP;
|
||||
{$endif}
|
||||
sym := GCurrentProcess.FindSymbol(a);
|
||||
if sym = nil
|
||||
then begin
|
||||
WriteLn(' [', FormatAddress(a), '] ???');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
symproc := sym;
|
||||
while not (symproc.kind in [skProcedure, skFunction]) do
|
||||
symproc := symproc.Parent;
|
||||
|
||||
if symproc = nil
|
||||
then WriteLn('???')
|
||||
else WriteLn(symproc.FileName, ':', symproc.Line, ' ', symproc.Name);
|
||||
|
||||
WriteLn(' [', FormatAddress(a), '] ', sym.FileName, ':', sym.Line, ' ', sym.Name);
|
||||
end;
|
||||
|
||||
begin
|
||||
repeat
|
||||
@ -415,7 +443,10 @@ begin
|
||||
until (GState in [dsStop, dsPause, dsQuit]);
|
||||
|
||||
if GState = dsPause
|
||||
then ShowDisas
|
||||
then begin
|
||||
ShowDisas;
|
||||
ShowCode;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -74,7 +74,7 @@ var
|
||||
R: Boolean;
|
||||
n: Integer;
|
||||
Is64: Boolean;
|
||||
SectionName: array[0..IMAGE_SIZEOF_SHORT_NAME] of Char;
|
||||
SectionName: array[0..255] of Char;
|
||||
begin
|
||||
if not ReadProcessMemory(AProcessHandle, Pointer(AAdress), @DosHeader, SizeOf(DosHeader), BytesRead)
|
||||
then begin
|
||||
@ -260,9 +260,28 @@ begin
|
||||
end;
|
||||
with SectionHeader do
|
||||
begin
|
||||
Move(Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0;
|
||||
WriteLN(' Name: ',SectionName);
|
||||
Write(' Name: ');
|
||||
if (Name[0] = Ord('/')) and (Name[1] in [Ord('0')..Ord('9')])
|
||||
then begin
|
||||
// long name
|
||||
|
||||
if ReadProcessMemory(
|
||||
AProcessHandle,
|
||||
Pointer(PtrUInt(AAdress + NTHeaders.FileHeader.PointerToSymbolTable + NTHeaders.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL + StrToIntDef(PChar(@Name[1]), 0))),
|
||||
@SectionName,
|
||||
SizeOf(SectionName),
|
||||
BytesRead
|
||||
)
|
||||
then WriteLn(SectionName)
|
||||
else WriteLn('Unable to retrieve sectionname @', PChar(@Name[1]));
|
||||
end
|
||||
else begin
|
||||
// short name
|
||||
Move(Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0; // make it #0 terminated
|
||||
WriteLn(SectionName);
|
||||
end;
|
||||
|
||||
WriteLN(' Misc.PhysicalAddress: ',FormatAddress(Misc.PhysicalAddress));
|
||||
WriteLN(' Misc.VirtualSize: ',Misc.VirtualSize);
|
||||
WriteLN(' VirtualAddress: ',FormatAddress(VirtualAddress));
|
||||
|
@ -39,7 +39,7 @@ unit WinDDwarf;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Types, SysUtils, WinDDwarfConst, Maps, Math, WinDLoader;
|
||||
Classes, Types, SysUtils, WinDebugger, WinDDwarfConst, Maps, Math, WinDLoader;
|
||||
|
||||
type
|
||||
// compilation unit header
|
||||
@ -136,6 +136,7 @@ type
|
||||
private
|
||||
FOwner: TDbgDwarf;
|
||||
FVerbose: Boolean;
|
||||
FValid: Boolean; // set if the compilationunit has compile unit tag.
|
||||
|
||||
// --- Header ---
|
||||
FLength: QWord; // length of info
|
||||
@ -183,6 +184,7 @@ type
|
||||
destructor Destroy; override;
|
||||
function GetDefinition(AAbbrev: Cardinal; out ADefinition: TDwarfAbbrev): Boolean;
|
||||
property FileName: String read FFileName;
|
||||
property Valid: Boolean read FValid;
|
||||
end;
|
||||
|
||||
{ TDwarfVerboseCompilationUnit }
|
||||
@ -223,8 +225,15 @@ type
|
||||
|
||||
|
||||
type
|
||||
TImageSection = (dsAbbrev, dsARanges, dsFrame, dsInfo, dsLine, dsLoc, dsMacinfo, dsPubNames, dsPubTypes, dsRanges, dsStr);
|
||||
TDwarfSection = dsAbbrev..dsStr;
|
||||
TDwarfSection = (dsAbbrev, dsARanges, dsFrame, dsInfo, dsLine, dsLoc, dsMacinfo, dsPubNames, dsPubTypes, dsRanges, dsStr);
|
||||
|
||||
TDwarfSectionInfo = record
|
||||
Section: TDwarfSection;
|
||||
VirtualAdress: QWord;
|
||||
Size: QWord; // the virtual size
|
||||
RawData: Pointer;
|
||||
end;
|
||||
PDwarfSectionInfo = ^TDwarfSectionInfo;
|
||||
|
||||
const
|
||||
DWARF_SECTION_NAME: array[TDwarfSection] of String = (
|
||||
@ -233,17 +242,10 @@ const
|
||||
'.debug_pubtypes', '.debug_ranges', '.debug_str'
|
||||
);
|
||||
|
||||
type
|
||||
TDwarfSectionInfo = record
|
||||
Section: TDwarfSection;
|
||||
VirtualAdress: QWord;
|
||||
Size: QWord; // the virtual size
|
||||
RawData: Pointer;
|
||||
end;
|
||||
|
||||
{ TDbgDwarf }
|
||||
|
||||
TDbgDwarf = class
|
||||
type
|
||||
TDbgDwarf = class(TDbgInfo)
|
||||
private
|
||||
FCompilationUnits: TList;
|
||||
FImageBase: QWord;
|
||||
@ -252,11 +254,11 @@ type
|
||||
protected
|
||||
function GetCompilationUnitClass: TDwarfCompilationUnitClass; virtual;
|
||||
public
|
||||
constructor Create(ALoader: TDbgImageLoader);
|
||||
constructor Create(ALoader: TDbgImageLoader); override;
|
||||
destructor Destroy; override;
|
||||
function LoadCompilationUnits: Integer;
|
||||
function PointerFromRVA(ARVA: QWord): Pointer;
|
||||
function PointerFromVA(ASection: TImageSection; AVA: QWord): Pointer;
|
||||
function PointerFromVA(ASection: TDwarfSection; AVA: QWord): Pointer;
|
||||
property CompilationUnits[AIndex: Integer]: TDwarfCompilationUnit read GetCompilationUnit;
|
||||
end;
|
||||
|
||||
@ -627,7 +629,7 @@ var
|
||||
Section: TDwarfSection;
|
||||
p: PDbgImageSection;
|
||||
begin
|
||||
inherited Create;
|
||||
inherited Create(ALoader);
|
||||
FCompilationUnits := TList.Create;
|
||||
FImageBase := ALoader.ImageBase;
|
||||
for Section := Low(Section) to High(Section) do
|
||||
@ -683,7 +685,7 @@ begin
|
||||
CU64^.AbbrevOffset,
|
||||
CU64^.AddressSize,
|
||||
True);
|
||||
p := @CU64^.Version + CU64^.Length;
|
||||
p := Pointer(@CU64^.Version) + CU64^.Length;
|
||||
end
|
||||
else begin
|
||||
if CU32^.Length = 0 then Break;
|
||||
@ -695,9 +697,10 @@ begin
|
||||
CU32^.AbbrevOffset,
|
||||
CU32^.AddressSize,
|
||||
False);
|
||||
p := @CU32^.Version + CU32^.Length;
|
||||
p := Pointer(@CU32^.Version) + CU32^.Length;
|
||||
end;
|
||||
FCompilationUnits.Add(CU);
|
||||
if CU.Valid then SetHasInfo;
|
||||
end;
|
||||
Result := FCompilationUnits.Count;
|
||||
end;
|
||||
@ -707,7 +710,7 @@ begin
|
||||
Result := Pointer(PtrUInt(FImageBase + ARVA));
|
||||
end;
|
||||
|
||||
function TDbgDwarf.PointerFromVA(ASection: TImageSection; AVA: QWord): Pointer;
|
||||
function TDbgDwarf.PointerFromVA(ASection: TDwarfSection; AVA: QWord): Pointer;
|
||||
begin
|
||||
Result := FSections[ASection].RawData + AVA - FImageBase - FSections[ASection].VirtualAdress;
|
||||
end;
|
||||
@ -731,29 +734,32 @@ var
|
||||
begin
|
||||
if AScope = nil then Exit;
|
||||
|
||||
if not LocateEntry(DW_TAG_subprogram, AScope, True, Scope, AttribList)
|
||||
then Exit;
|
||||
|
||||
Info.Scope := Scope;
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_low_pc, AttribList, Attrib, Form)
|
||||
if LocateEntry(DW_TAG_subprogram, AScope, True, Scope, AttribList)
|
||||
then begin
|
||||
ReadValue(Attrib, Form, Info.StartPC);
|
||||
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_name, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, Info.Name)
|
||||
else Info.Name := 'undefined';
|
||||
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_high_pc, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, Info.EndPC)
|
||||
else Info.EndPC := Info.StartPC;
|
||||
|
||||
Info.LineInfo := nil; // filled in when the first time needed
|
||||
if Info.StartPC <> 0
|
||||
Info.Scope := Scope;
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_low_pc, AttribList, Attrib, Form)
|
||||
then begin
|
||||
if FAddressMap.HasId(Info.StartPC)
|
||||
then WriteLN('WARNING duplicate start adress: ', IntToHex(Info.StartPC, FAddressSize * 2))
|
||||
else FAddressMap.Add(Info.StartPC, Info);
|
||||
ReadValue(Attrib, Form, Info.StartPC);
|
||||
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_name, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, Info.Name)
|
||||
else Info.Name := 'undefined';
|
||||
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_high_pc, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, Info.EndPC)
|
||||
else Info.EndPC := Info.StartPC;
|
||||
|
||||
Info.LineInfo := nil; // filled in when the first time needed
|
||||
if Info.StartPC <> 0
|
||||
then begin
|
||||
if FAddressMap.HasId(Info.StartPC)
|
||||
then WriteLN('WARNING duplicate start adress: ', IntToHex(Info.StartPC, FAddressSize * 2))
|
||||
else FAddressMap.Add(Info.StartPC, Info);
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
Scope := AScope;
|
||||
end;
|
||||
|
||||
BuildAddessMap(Scope^.Child);
|
||||
@ -765,7 +771,7 @@ var
|
||||
AttribList: TPointerDynArray;
|
||||
Attrib: Pointer;
|
||||
Form: Cardinal;
|
||||
StatementList: QWord;
|
||||
StatementList, Ofs: QWord;
|
||||
Scope: PDwarfScopeInfo;
|
||||
begin
|
||||
inherited Create;
|
||||
@ -774,6 +780,17 @@ begin
|
||||
FLength := ALength;
|
||||
FVersion := AVersion;
|
||||
FAbbrevOffset := AAbbrevOffset;
|
||||
// check for address as offset
|
||||
if FAbbrevOffset > FOwner.FSections[dsAbbrev].Size
|
||||
then begin
|
||||
Ofs := FAbbrevOffset - FOwner.FImageBase - FOwner.FSections[dsAbbrev].VirtualAdress;
|
||||
if (Ofs >= 0) and (Ofs < FOwner.FSections[dsAbbrev].Size)
|
||||
then begin
|
||||
WriteLN('WARNING: Got Abbrev ofset as address, adjusting..');
|
||||
FAbbrevOffset := Ofs;
|
||||
end;
|
||||
end;
|
||||
|
||||
FAddressSize := AAddressSize;
|
||||
FIsDwarf64 := AIsDwarf64;
|
||||
|
||||
@ -793,6 +810,7 @@ begin
|
||||
WriteLN('WARNING compilation unit has no compile_unit tag');
|
||||
Exit;
|
||||
end;
|
||||
FValid := True;
|
||||
|
||||
if LocateAttribute(Scope^.Entry, DW_AT_name, AttribList, Attrib, Form)
|
||||
then ReadValue(Attrib, Form, FFileName);
|
||||
@ -830,6 +848,7 @@ destructor TDwarfCompilationUnit.Destroy;
|
||||
if Scope^.Next = nil
|
||||
then begin
|
||||
Scope := Scope^.Parent;
|
||||
if Scope = nil then Break;
|
||||
Scope^.Child := nil;
|
||||
end
|
||||
else Scope := Scope^.Next;
|
||||
@ -2044,14 +2063,14 @@ begin
|
||||
if LNP64^.Signature = DWARF_HEADER64_SIGNATURE
|
||||
then begin
|
||||
UnitLength := LNP64^.UnitLength;
|
||||
DataEnd := @LNP64^.Version + UnitLength;
|
||||
DataEnd := Pointer(@LNP64^.Version) + UnitLength;
|
||||
Version := LNP64^.Version;
|
||||
HeaderLength := LNP64^.HeaderLength;
|
||||
Info := @LNP64^.Info;
|
||||
end
|
||||
else begin
|
||||
UnitLength := LNP32^.UnitLength;
|
||||
DataEnd := @LNP32^.Version + UnitLength;
|
||||
DataEnd := Pointer(@LNP32^.Version) + UnitLength;
|
||||
Version := LNP32^.Version;
|
||||
HeaderLength := LNP32^.HeaderLength;
|
||||
Info := @LNP32^.Info;
|
||||
|
@ -36,7 +36,7 @@ unit WinDebugger;
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Classes, Maps, WindExtra;
|
||||
Windows, Classes, Maps, WinDExtra, WinDLoader;
|
||||
|
||||
type
|
||||
TDbgProcess = class;
|
||||
@ -136,6 +136,20 @@ type
|
||||
property Children[AIndex: Integer]: TDbgSymbol read GetChild;
|
||||
end;
|
||||
|
||||
|
||||
TDbgInfo = class(TObject)
|
||||
private
|
||||
FHasInfo: Boolean;
|
||||
protected
|
||||
procedure SetHasInfo;
|
||||
public
|
||||
constructor Create(ALoader: TDbgImageLoader); virtual;
|
||||
function FindSymbol(const AName: String): TDbgSymbol; virtual;
|
||||
function FindSymbol(AAdress: TDbgPtr): TDbgSymbol; virtual;
|
||||
property HasInfo: Boolean read FHasInfo;
|
||||
end;
|
||||
|
||||
|
||||
TDbgBreakpoint = class;
|
||||
TDbgBreakpointEvent = procedure(const ASender: TDbgBreakpoint; const AContext: TContext) of object;
|
||||
TDbgBreakpoint = class(TObject)
|
||||
@ -162,8 +176,10 @@ type
|
||||
FModuleHandle: THandle;
|
||||
FBaseAddr: TDbgPtr;
|
||||
FBreakList: TList;
|
||||
FSymbols: TDbgSymbol;
|
||||
procedure BuildSymbols;
|
||||
FDbgInfo: TDbgInfo;
|
||||
FLoader: TDbgImageLoader;
|
||||
|
||||
procedure LoadInfo;
|
||||
procedure CheckName;
|
||||
procedure SetName(const AValue: String);
|
||||
public
|
||||
@ -181,6 +197,8 @@ type
|
||||
property Name: String read FName;
|
||||
end;
|
||||
|
||||
{ TDbgProcess }
|
||||
|
||||
TDbgProcess = class(TDbgInstance)
|
||||
private
|
||||
FProcessID: Integer;
|
||||
@ -190,6 +208,8 @@ type
|
||||
FThreadMap: TMap; // map ThreadID -> ThreadObject
|
||||
FLibMap: TMap; // map LibAddr -> LibObject
|
||||
FBreakMap: TMap; // map BreakAddr -> BreakObject
|
||||
|
||||
FSymInstances: TList; // list of dbgInstances with debug info
|
||||
|
||||
FMainThread: TDbgThread;
|
||||
|
||||
@ -207,6 +227,8 @@ type
|
||||
function AddBreak(const ALocation: TDbgPtr): TDbgBreakpoint;
|
||||
function AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
|
||||
procedure AddThread(const AID: Integer; const AInfo: TCreateThreadDebugInfo);
|
||||
function FindSymbol(const AName: String): TDbgSymbol;
|
||||
function FindSymbol(AAdress: TDbgPtr): TDbgSymbol;
|
||||
function GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;
|
||||
function GetThread(const AID: Integer; out AThread: TDbgThread): Boolean;
|
||||
procedure Interrupt;
|
||||
@ -232,7 +254,7 @@ type
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils, WinDSymbols;
|
||||
SysUtils, WinDSymbols, WinDDwarf;
|
||||
|
||||
procedure LogLastError;
|
||||
begin
|
||||
@ -241,16 +263,10 @@ end;
|
||||
|
||||
{ TDbgInstance }
|
||||
|
||||
procedure TDbgInstance.BuildSymbols;
|
||||
begin
|
||||
FSymbols := TDbgSymbol.Create(FName, skInstance, FBaseAddr);
|
||||
AddSymbols(FSymbols, FModuleHandle);
|
||||
end;
|
||||
|
||||
procedure TDbgInstance.CheckName;
|
||||
begin
|
||||
if FName = ''
|
||||
then FName := Format('@%p', [FBaseAddr]);
|
||||
then FName := Format('@%p', [Pointer(PtrUInt(FBaseAddr))]);
|
||||
end;
|
||||
|
||||
constructor TDbgInstance.Create(const AProcess: TDbgProcess; const ADefaultName: String; const AModuleHandle: THandle; const ABaseAddr, ANameAddr: TDbgPtr; const AUnicode: Boolean);
|
||||
@ -297,7 +313,8 @@ begin
|
||||
then W := ADefaultName;
|
||||
|
||||
SetName(W);
|
||||
BuildSymbols;
|
||||
|
||||
LoadInfo;
|
||||
end;
|
||||
|
||||
destructor TDbgInstance.Destroy;
|
||||
@ -311,10 +328,18 @@ begin
|
||||
FBreakList.Clear;
|
||||
|
||||
FreeAndNil(FBreakList);
|
||||
FreeAndNil(FSymbols);
|
||||
FreeAndNil(FDbgInfo);
|
||||
FreeAndNil(FLoader);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TDbgInstance.LoadInfo;
|
||||
begin
|
||||
FLoader := TDbgWinPEImageLoader.Create(FModuleHandle);
|
||||
FDbgInfo := TDbgDwarf.Create(FLoader);
|
||||
TDbgDwarf(FDbgInfo).LoadCompilationUnits;
|
||||
end;
|
||||
|
||||
procedure TDbgInstance.SetName(const AValue: String);
|
||||
begin
|
||||
FName := AValue;
|
||||
@ -340,6 +365,8 @@ function TDbgProcess.AddLib(const AInfo: TLoadDLLDebugInfo): TDbgLibrary;
|
||||
begin
|
||||
Result := TDbgLibrary.Create(Self, HexValue(AInfo.lpBaseOfDll, SizeOf(Pointer), [hvfIncludeHexchar]), AInfo);
|
||||
FLibMap.Add(TDbgPtr(AInfo.lpBaseOfDll), Result);
|
||||
if Result.FDbgInfo.HasInfo
|
||||
then FSymInstances.Add(Result);
|
||||
end;
|
||||
|
||||
procedure TDbgProcess.AddThread(const AID: Integer; const AInfo: TCreateThreadDebugInfo);
|
||||
@ -383,10 +410,15 @@ begin
|
||||
FBreakMap := TMap.Create(MAP_ID_SIZE, SizeOf(TDbgBreakpoint));
|
||||
FSingleStepBreak := nil;
|
||||
|
||||
FSymInstances := TList.Create;
|
||||
|
||||
inherited Create(Self, ADefaultName, AInfo.hFile, TDbgPtr(AInfo.lpBaseOfImage), TDbgPtr(AInfo.lpImageName), AInfo.fUnicode <> 0);
|
||||
|
||||
FMainThread := TDbgThread.Create(Self, AThreadID, FInfo.hThread, FInfo.lpThreadLocalBase, FInfo.lpStartAddress);
|
||||
FMainThread := TDbgThread.Create(Self, AThreadID, AInfo.hThread, AInfo.lpThreadLocalBase, AInfo.lpStartAddress);
|
||||
FThreadMap.Add(AThreadID, FMainThread);
|
||||
|
||||
if FDbgInfo.HasInfo
|
||||
then FSymInstances.Add(Self);
|
||||
end;
|
||||
|
||||
destructor TDbgProcess.Destroy;
|
||||
@ -396,9 +428,29 @@ begin
|
||||
FreeAndNil(FBreakMap);
|
||||
FreeAndNil(FThreadMap);
|
||||
FreeAndNil(FLibMap);
|
||||
FreeAndNil(FSymInstances);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TDbgProcess.FindSymbol(const AName: String): TDbgSymbol;
|
||||
begin
|
||||
Result := FDbgInfo.FindSymbol(AName);
|
||||
end;
|
||||
|
||||
function TDbgProcess.FindSymbol(AAdress: TDbgPtr): TDbgSymbol;
|
||||
var
|
||||
n: Integer;
|
||||
Inst: TDbgInstance;
|
||||
begin
|
||||
for n := 0 to FSymInstances.Count - 1 do
|
||||
begin
|
||||
Inst := TDbgInstance(FSymInstances[n]);
|
||||
Result := Inst.FDbgInfo.FindSymbol(AAdress);
|
||||
if Result <> nil then Exit;
|
||||
end;
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TDbgProcess.GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;
|
||||
var
|
||||
Iterator: TMapIterator;
|
||||
@ -602,9 +654,15 @@ begin
|
||||
end;
|
||||
|
||||
procedure TDbgProcess.RemoveLib(const AInfo: TUnloadDLLDebugInfo);
|
||||
var
|
||||
Lib: TDbgLibrary;
|
||||
begin
|
||||
if FLibMap = nil then Exit;
|
||||
if not FLibMap.GetData(TDbgPtr(AInfo.lpBaseOfDll), Lib) then Exit;
|
||||
if Lib.FDbgInfo.HasInfo
|
||||
then FSymInstances.Remove(Lib);
|
||||
FLibMap.Delete(TDbgPtr(AInfo.lpBaseOfDll));
|
||||
// TODO: Free lib ???
|
||||
end;
|
||||
|
||||
procedure TDbgProcess.RemoveThread(const AID: DWord);
|
||||
@ -681,6 +739,29 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ TDbgInfo }
|
||||
|
||||
constructor TDbgInfo.Create(ALoader: TDbgImageLoader);
|
||||
begin
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
function TDbgInfo.FindSymbol(const AName: String): TDbgSymbol;
|
||||
begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TDbgInfo.FindSymbol(AAdress: TDbgPtr): TDbgSymbol;
|
||||
begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
procedure TDbgInfo.SetHasInfo;
|
||||
begin
|
||||
FHasInfo := True;
|
||||
end;
|
||||
|
||||
|
||||
{ TDbgSymbol }
|
||||
|
||||
function TDbgSymbol.GetChild(AIndex: Integer): TDbgSymbol;
|
||||
|
@ -127,7 +127,7 @@ begin
|
||||
nil,
|
||||
AErrorCode,
|
||||
LANG_NEUTRAL,
|
||||
@Temp,
|
||||
Pointer(@Temp), // the fuction needs either a PChar or a PPChar, depending on FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
0,
|
||||
nil);
|
||||
if R = 0
|
||||
|
@ -56,7 +56,6 @@ type
|
||||
|
||||
TDbgImageLoader = class(TObject)
|
||||
private
|
||||
FFileName: String;
|
||||
FImage64Bit: Boolean;
|
||||
FImageBase: QWord;
|
||||
FSections: TStringList;
|
||||
@ -68,9 +67,8 @@ type
|
||||
procedure LoadSections; virtual; abstract;
|
||||
procedure UnloadSections; virtual; abstract;
|
||||
public
|
||||
constructor Create(const AFileName: String); virtual;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
property FileName: String read FFileName;
|
||||
property ImageBase: QWord read FImageBase;
|
||||
Property Image64Bit: Boolean read FImage64Bit;
|
||||
property Section[const AName: String]: PDbgImageSection read GetSection;
|
||||
@ -97,10 +95,11 @@ type
|
||||
FModulePtr: Pointer;
|
||||
procedure DoCleanup;
|
||||
protected
|
||||
constructor Create(const AFileName: String); override;
|
||||
function LoadData(out AModuleBase: Pointer; out AHeaders: PImageNtHeaders): Boolean; override;
|
||||
procedure UnloadData; override;
|
||||
public
|
||||
constructor Create(const AFileName: String);
|
||||
constructor Create(AFileHandle: THandle);
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -120,10 +119,9 @@ begin
|
||||
FSections.Objects[idx] := TObject(p);
|
||||
end;
|
||||
|
||||
constructor TDbgImageLoader.Create(const AFileName: String);
|
||||
constructor TDbgImageLoader.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
FFileName := AFileName;
|
||||
FSections := TStringList.Create;
|
||||
FSections.Sorted := True;
|
||||
FSections.Duplicates := dupError;
|
||||
@ -192,7 +190,7 @@ begin
|
||||
|
||||
for n := 0 to NtHeaders^.FileHeader.NumberOfSections - 1 do
|
||||
begin
|
||||
SectionHeader := @NtHeaders^.OptionalHeader + NtHeaders^.FileHeader.SizeOfOptionalHeader + SizeOf(SectionHeader^) * n;
|
||||
SectionHeader := Pointer(@NtHeaders^.OptionalHeader) + NtHeaders^.FileHeader.SizeOfOptionalHeader + SizeOf(SectionHeader^) * n;
|
||||
// make a null terminated name
|
||||
Move(SectionHeader^.Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0;
|
||||
@ -218,10 +216,22 @@ end;
|
||||
|
||||
constructor TDbgWinPEImageLoader.Create(const AFileName: String);
|
||||
begin
|
||||
FFileHandle := INVALID_HANDLE_VALUE;
|
||||
FMapHandle := 0;
|
||||
FModulePtr := nil;
|
||||
inherited Create(AFileName);
|
||||
FFileHandle := CreateFile(PChar(AFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if FFileHandle = INVALID_HANDLE_VALUE
|
||||
then begin
|
||||
WriteLN('Cannot open file: ', AFileName);
|
||||
end;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
constructor TDbgWinPEImageLoader.Create(AFileHandle: THandle);
|
||||
begin
|
||||
FFileHandle := AFileHandle;
|
||||
if FFileHandle = INVALID_HANDLE_VALUE
|
||||
then begin
|
||||
WriteLN('Invalid file handle');
|
||||
end;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
procedure TDbgWinPEImageLoader.DoCleanup;
|
||||
@ -243,12 +253,6 @@ var
|
||||
DosHeader: PImageDosHeader;
|
||||
begin
|
||||
Result := False;
|
||||
FFileHandle := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if FFileHandle = INVALID_HANDLE_VALUE
|
||||
then begin
|
||||
WriteLN('Cannot open file: ', FileName);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
try
|
||||
FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READONLY{ or SEC_IMAGE}, 0, 0, nil);
|
||||
|
@ -198,7 +198,7 @@ begin
|
||||
Sections.Sorted := True;
|
||||
for n := 0 to NtHeaders^.FileHeader.NumberOfSections - 1 do
|
||||
begin
|
||||
SectionHeader := @NTHeaders^.OptionalHeader + NTHeaders^.FileHeader.SizeOfOptionalHeader + SizeOf(SectionHeader^) * n;
|
||||
SectionHeader := Pointer(@NTHeaders^.OptionalHeader) + NTHeaders^.FileHeader.SizeOfOptionalHeader + SizeOf(SectionHeader^) * n;
|
||||
// make a null terminated name
|
||||
Move(SectionHeader^.Name, SectionName, IMAGE_SIZEOF_SHORT_NAME);
|
||||
SectionName[IMAGE_SIZEOF_SHORT_NAME] := #0;
|
||||
|
Loading…
Reference in New Issue
Block a user