mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 14:49:29 +02:00
LazDebuggerFp, FpDebug: Disassembler now annotates lines with call,jmp,je,... with info on the target address.
This commit is contained in:
parent
57e0738de1
commit
ee4e48864e
@ -1010,6 +1010,9 @@ type
|
||||
SrcFileLine: Integer; // Line in SrcFile
|
||||
SrcStatementIndex: SmallInt; // Index of Statement, within list of Stmnt of the same SrcLine
|
||||
SrcStatementCount: SmallInt; // Count of Statements for this SrcLine
|
||||
TargetAddr: TDbgPtr; // Absolute Addr for relative jump/call
|
||||
TargetName, TargetFile: String;
|
||||
TargetLine: Integer;
|
||||
end;
|
||||
|
||||
TDisassemblerAddressValidity =
|
||||
|
@ -632,6 +632,11 @@ type
|
||||
function InstructionLength: Integer; virtual;
|
||||
end;
|
||||
|
||||
TDbgInstInfo = record
|
||||
InstrType: (itAny, itJump);
|
||||
InstrTargetOffs: Int64; // offset from the START address of instruction
|
||||
end;
|
||||
|
||||
{ TDbgAsmDecoder }
|
||||
|
||||
TDbgAsmDecoder = class
|
||||
@ -643,7 +648,8 @@ type
|
||||
public
|
||||
constructor Create(AProcess: TDbgProcess); virtual; abstract;
|
||||
|
||||
procedure Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String); virtual; abstract;
|
||||
procedure Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String; out AnInfo: TDbgInstInfo); virtual; overload;
|
||||
procedure Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String); virtual; abstract; overload;
|
||||
procedure ReverseDisassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String); virtual;
|
||||
|
||||
function GetInstructionInfo(AnAddress: TDBGPtr): TDbgAsmInstruction; virtual; abstract;
|
||||
@ -1830,6 +1836,13 @@ begin
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
procedure TDbgAsmDecoder.Disassemble(var AAddress: Pointer; out
|
||||
ACodeBytes: String; out ACode: String; out AnInfo: TDbgInstInfo);
|
||||
begin
|
||||
AnInfo := Default(TDbgInstInfo);
|
||||
Disassemble(AAddress, ACodeBytes, ACode);
|
||||
end;
|
||||
|
||||
// Naive backwards scanner, decode MaxInstructionSize
|
||||
// if pointer to next instruction matches, done!
|
||||
// If not decrease instruction size and try again.
|
||||
|
@ -562,6 +562,7 @@ type
|
||||
constructor Create(AProcess: TDbgProcess); override;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String; out AnInfo: TDbgInstInfo); override;
|
||||
procedure Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String); override;
|
||||
function GetInstructionInfo(AnAddress: TDBGPtr): TDbgAsmInstruction; override;
|
||||
|
||||
@ -4915,7 +4916,8 @@ begin
|
||||
Result := FInstruction.OpCode.Opcode;
|
||||
end;
|
||||
|
||||
procedure TX86AsmDecoder.Disassemble(var AAddress: Pointer; out ACodeBytes: String; out ACode: String);
|
||||
procedure TX86AsmDecoder.Disassemble(var AAddress: Pointer; out
|
||||
ACodeBytes: String; out ACode: String; out AnInfo: TDbgInstInfo);
|
||||
const
|
||||
MEMPTR: array[TOperandSize] of string = (
|
||||
{ os0 } '',
|
||||
@ -4938,10 +4940,12 @@ var
|
||||
Instr: TInstruction;
|
||||
S, Soper: String;
|
||||
n, i: Integer;
|
||||
TargetAddrOffs: Int64;
|
||||
HasMem: Boolean;
|
||||
OpcodeName: String;
|
||||
Code: PByte;
|
||||
begin
|
||||
AnInfo := default(TDbgInstInfo);
|
||||
Code := AAddress;
|
||||
Disassembler.Disassemble(FProcess.Mode, AAddress, Instr);
|
||||
|
||||
@ -4989,6 +4993,28 @@ begin
|
||||
{$endif}
|
||||
|
||||
|
||||
if (Instr.OpCode.Opcode in [OPcall, OPj__, OPjcxz, OPjecxz, OPjmp, OPjmpe, OPjrcxz]) and
|
||||
(Instr.OperCnt = 1) and
|
||||
(hvfSigned in Instr.Operand[1].FormatFlags)
|
||||
then begin
|
||||
TargetAddrOffs := 1;
|
||||
case Instr.Operand[1].ByteCount of
|
||||
1: TargetAddrOffs := smallint(PByte(@Code[Instr.Operand[1].CodeIndex])^);
|
||||
2: TargetAddrOffs := shortint(PWord(@Code[Instr.Operand[1].CodeIndex])^);
|
||||
4: TargetAddrOffs := Integer(PDWord(@Code[Instr.Operand[1].CodeIndex])^);
|
||||
8: TargetAddrOffs := Int64(PQWord(@Code[Instr.Operand[1].CodeIndex])^);
|
||||
end;
|
||||
if TargetAddrOffs <> 1 then begin
|
||||
AnInfo.InstrType := itJump;
|
||||
{$PUSH}{$R-}{$Q-}
|
||||
if not (hvfPrefixPositive in Instr.Operand[1].FormatFlags) then
|
||||
TargetAddrOffs := -TargetAddrOffs;
|
||||
AnInfo.InstrTargetOffs := TDbgPtr(AAddress) - TDbgPtr(Code) + TargetAddrOffs;
|
||||
{$POP}
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
OpcodeName := OPCODE_PREFIX[Instr.OpCode.Prefix];
|
||||
OpcodeName := OpcodeName + OPCODE_NAME[Instr.OpCode.Opcode];
|
||||
OpcodeName := OpcodeName + OPCODE_SUFFIX[Instr.OpCode.Suffix];
|
||||
@ -5021,6 +5047,14 @@ begin
|
||||
ACodeBytes := S;
|
||||
end;
|
||||
|
||||
procedure TX86AsmDecoder.Disassemble(var AAddress: Pointer; out
|
||||
ACodeBytes: String; out ACode: String);
|
||||
var
|
||||
AnInfo: TDbgInstInfo;
|
||||
begin
|
||||
Disassemble(AAddress, ACodeBytes, ACode, AnInfo);
|
||||
end;
|
||||
|
||||
function TX86AsmDecoder.GetInstructionInfo(AnAddress: TDBGPtr): TDbgAsmInstruction;
|
||||
begin
|
||||
if (FLastInstr = nil) or (FLastInstr.RefCount > 1) then begin
|
||||
|
@ -2136,6 +2136,7 @@ var
|
||||
ADisassembler: TDbgAsmDecoder;
|
||||
AOffset: longint;
|
||||
RealReadLen: Cardinal;
|
||||
AnInfo: TDbgInstInfo;
|
||||
|
||||
procedure AddInfoToRange(ALineAddr: TDBGPtr; ATargetRange: TDBGDisassemblerEntryRange);
|
||||
var
|
||||
@ -2176,6 +2177,27 @@ var
|
||||
AnEntry.FuncName := AFuncName;
|
||||
AnEntry.SrcStatementIndex:=StatIndex;
|
||||
AnEntry.Offset := AOffset;
|
||||
AnEntry.TargetAddr := 0;
|
||||
AnEntry.TargetName := '';
|
||||
AnEntry.TargetFile := '';
|
||||
AnEntry.TargetLine := 0;
|
||||
if AnInfo.InstrType = itJump then begin
|
||||
{$PUSH}{$R-}{$Q-}
|
||||
AnEntry.TargetAddr := ALineAddr + AnInfo.InstrTargetOffs;
|
||||
{$POP}
|
||||
Sym := TFpDebugDebugger(Debugger).FDbgController.CurrentProcess.FindProcSymbol(AnEntry.TargetAddr);
|
||||
if Sym <> nil then begin
|
||||
AnEntry.TargetName := Sym.Name;
|
||||
AnEntry.TargetFile := Sym.FileName;
|
||||
AnEntry.TargetLine := Sym.Line;
|
||||
{$PUSH}{$R-}{$Q-}
|
||||
AOffset := int32(int64(AnEntry.TargetAddr) - int64(Sym.Address.Address));
|
||||
{$POP}
|
||||
if AOffset <> 0 then
|
||||
AnEntry.TargetName := AnEntry.TargetName + '+' + IntToStr(AOffset);
|
||||
Sym.ReleaseReference;
|
||||
end;
|
||||
end;
|
||||
ATargetRange.Append(@AnEntry);
|
||||
inc(StatIndex);
|
||||
end;
|
||||
@ -2284,7 +2306,7 @@ begin
|
||||
else begin
|
||||
while tmpAddr < AnAddr do begin
|
||||
p := @CodeBin[bytesDisassembled];
|
||||
ADisassembler.Disassemble(p, ADump, AStatement);
|
||||
ADisassembler.Disassemble(p, ADump, AStatement, AnInfo);
|
||||
|
||||
prevInstructionSize := p - @CodeBin[bytesDisassembled];
|
||||
if prevInstructionSize = 0 then
|
||||
@ -2308,6 +2330,10 @@ begin
|
||||
AnEntry.FuncName := '';
|
||||
AnEntry.SrcStatementIndex:=StatIndex;
|
||||
AnEntry.Offset := -1;
|
||||
AnEntry.TargetAddr := 0;
|
||||
AnEntry.TargetName := '';
|
||||
AnEntry.TargetFile := '';
|
||||
AnEntry.TargetLine := 0;
|
||||
ARange.Append(@AnEntry);
|
||||
inc(StatIndex);
|
||||
end;
|
||||
@ -2332,7 +2358,7 @@ begin
|
||||
for i := 0 to ALinesAfter-1 do
|
||||
begin
|
||||
p := @CodeBin[bytesDisassembled];
|
||||
ADisassembler.Disassemble(p, ADump, AStatement);
|
||||
ADisassembler.Disassemble(p, ADump, AStatement, AnInfo);
|
||||
|
||||
prevInstructionSize := p - @CodeBin[bytesDisassembled];
|
||||
bytesDisassembled := bytesDisassembled + prevInstructionSize;
|
||||
|
@ -44,6 +44,7 @@ type
|
||||
FileName, FullFileName: String;
|
||||
SourceLine: Integer;
|
||||
ImageIndex: Integer;
|
||||
TargetAddr: TDbgPtr; // Absolute Addr for relative jump/call
|
||||
end;
|
||||
TAsmDlgLineEntries = Array of TAsmDlgLineEntry;
|
||||
|
||||
@ -1068,7 +1069,7 @@ var
|
||||
DoneLocation: TDBGPtr;
|
||||
DoneTopLine, DoneLineCount: Integer;
|
||||
DoneCountBefore, DoneCountAfter: Integer;
|
||||
Line, Idx: Integer;
|
||||
Line, Idx, W: Integer;
|
||||
Itm, NextItm, PrevItm: PDisassemblerEntry;
|
||||
LineIsSrc, HasLineOutOfRange: Boolean;
|
||||
s: String;
|
||||
@ -1091,6 +1092,11 @@ begin
|
||||
end;
|
||||
FUpdating := True;
|
||||
|
||||
if FDebugger = nil
|
||||
then W := 16
|
||||
else W := FDebugger.TargetWidth div 4;
|
||||
|
||||
|
||||
try
|
||||
FUpdateNeeded := False;
|
||||
DoneLocation := FCurrentLocation;
|
||||
@ -1260,6 +1266,23 @@ begin
|
||||
ALineMap[Line].Statement := Itm^.Statement;
|
||||
ALineMap[Line].SourceLine := Itm^.SrcFileLine;
|
||||
ALineMap[Line].ImageIndex := -1;
|
||||
ALineMap[Line].TargetAddr := Itm^.TargetAddr;
|
||||
|
||||
s := StringOfChar(' ', min(4, 40 - Length(ALineMap[Line].Statement))) + '#';
|
||||
if Itm^.TargetAddr <> 0 then begin
|
||||
ALineMap[Line].Statement := ALineMap[Line].Statement + s + ' $' + IntToHex(Itm^.TargetAddr, W);
|
||||
s := '';
|
||||
end;
|
||||
if Itm^.TargetName <> '' then begin
|
||||
ALineMap[Line].Statement := ALineMap[Line].Statement + s + ' ' + Itm^.TargetName;
|
||||
s := '';
|
||||
end;
|
||||
if Itm^.TargetFile <> '' then begin
|
||||
ALineMap[Line].Statement := ALineMap[Line].Statement + s + ' ' + ExtractFileName(Itm^.TargetFile);
|
||||
if Itm^.TargetLine <> 0 then
|
||||
ALineMap[Line].Statement := ALineMap[Line].Statement + ':' + IntToStr(Itm^.TargetLine);
|
||||
s := '';
|
||||
end;
|
||||
|
||||
inc(Line);
|
||||
inc(idx);
|
||||
|
Loading…
Reference in New Issue
Block a user