mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-29 21:42:28 +01:00
DBG: Refactor Disassembler
git-svn-id: trunk@28360 -
This commit is contained in:
parent
4eaba3647b
commit
dee17fe6e4
@ -1030,6 +1030,7 @@ type
|
|||||||
property OnCurrent: TNotifyEvent read FOnCurrent write FOnCurrent;
|
property OnCurrent: TNotifyEvent read FOnCurrent write FOnCurrent;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{%region ***** Disassembler ***** }
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(** **)
|
(** **)
|
||||||
@ -1150,9 +1151,19 @@ type
|
|||||||
TDBGDisassemblerEntryMapMergeEvent
|
TDBGDisassemblerEntryMapMergeEvent
|
||||||
= procedure(MergeReceiver, MergeGiver: TDBGDisassemblerEntryRange) of object;
|
= procedure(MergeReceiver, MergeGiver: TDBGDisassemblerEntryRange) of object;
|
||||||
|
|
||||||
|
{ TDBGDisassemblerEntryMapIterator }
|
||||||
|
TDBGDisassemblerEntryMap = class;
|
||||||
|
|
||||||
|
TDBGDisassemblerEntryMapIterator = class(TMapIterator)
|
||||||
|
public
|
||||||
|
function GetRangeForAddr(AnAddr: TDbgPtr; IncludeNextAddr: Boolean = False): TDBGDisassemblerEntryRange;
|
||||||
|
function NextRange: TDBGDisassemblerEntryRange;
|
||||||
|
function PreviousRange: TDBGDisassemblerEntryRange;
|
||||||
|
end;
|
||||||
|
|
||||||
TDBGDisassemblerEntryMap = class(TMap)
|
TDBGDisassemblerEntryMap = class(TMap)
|
||||||
private
|
private
|
||||||
FIterator: TMapIterator;
|
FIterator: TDBGDisassemblerEntryMapIterator;
|
||||||
FOnDelete: TNotifyEvent;
|
FOnDelete: TNotifyEvent;
|
||||||
FOnMerge: TDBGDisassemblerEntryMapMergeEvent;
|
FOnMerge: TDBGDisassemblerEntryMapMergeEvent;
|
||||||
FFreeItemLock: Boolean;
|
FFreeItemLock: Boolean;
|
||||||
@ -1200,6 +1211,7 @@ type
|
|||||||
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{%endregion ^^^^^ Disassembler ^^^^^ }
|
||||||
|
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
(******************************************************************************)
|
(******************************************************************************)
|
||||||
@ -5168,6 +5180,46 @@ begin
|
|||||||
AOffs := AnAddr - FEntries[Result].Addr;
|
AOffs := AnAddr - FEntries[Result].Addr;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TDBGDisassemblerEntryMapIterator }
|
||||||
|
|
||||||
|
function TDBGDisassemblerEntryMapIterator.GetRangeForAddr(AnAddr: TDbgPtr;
|
||||||
|
IncludeNextAddr: Boolean): TDBGDisassemblerEntryRange;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if not Locate(AnAddr)
|
||||||
|
then if not BOM
|
||||||
|
then Previous;
|
||||||
|
|
||||||
|
if BOM
|
||||||
|
then exit;
|
||||||
|
|
||||||
|
GetData(Result);
|
||||||
|
if not Result.ContainsAddr(AnAddr, IncludeNextAddr)
|
||||||
|
then Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDBGDisassemblerEntryMapIterator.NextRange: TDBGDisassemblerEntryRange;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if EOM
|
||||||
|
then exit;
|
||||||
|
|
||||||
|
Next;
|
||||||
|
if not EOM
|
||||||
|
then GetData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDBGDisassemblerEntryMapIterator.PreviousRange: TDBGDisassemblerEntryRange;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
if BOM
|
||||||
|
then exit;
|
||||||
|
|
||||||
|
Previous;
|
||||||
|
if not BOM
|
||||||
|
then GetData(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDBGDisassemblerEntryMap }
|
{ TDBGDisassemblerEntryMap }
|
||||||
|
|
||||||
procedure TDBGDisassemblerEntryMap.ReleaseData(ADataPtr: Pointer);
|
procedure TDBGDisassemblerEntryMap.ReleaseData(ADataPtr: Pointer);
|
||||||
@ -5184,7 +5236,7 @@ end;
|
|||||||
constructor TDBGDisassemblerEntryMap.Create(AIdType: TMapIdType; ADataSize: Cardinal);
|
constructor TDBGDisassemblerEntryMap.Create(AIdType: TMapIdType; ADataSize: Cardinal);
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
FIterator := TMapIterator.Create(Self);
|
FIterator := TDBGDisassemblerEntryMapIterator.Create(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TDBGDisassemblerEntryMap.Destroy;
|
destructor TDBGDisassemblerEntryMap.Destroy;
|
||||||
@ -5249,17 +5301,7 @@ end;
|
|||||||
function TDBGDisassemblerEntryMap.GetRangeForAddr(AnAddr: TDbgPtr;
|
function TDBGDisassemblerEntryMap.GetRangeForAddr(AnAddr: TDbgPtr;
|
||||||
IncludeNextAddr: Boolean = False): TDBGDisassemblerEntryRange;
|
IncludeNextAddr: Boolean = False): TDBGDisassemblerEntryRange;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := FIterator.GetRangeForAddr(AnAddr, IncludeNextAddr);
|
||||||
if not FIterator.Locate(AnAddr)
|
|
||||||
then if not FIterator.BOM
|
|
||||||
then FIterator.Previous;
|
|
||||||
|
|
||||||
if FIterator.BOM
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
FIterator.GetData(Result);
|
|
||||||
if not Result.ContainsAddr(AnAddr, IncludeNextAddr)
|
|
||||||
then Result := nil;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TDBGDisassembler }
|
{ TDBGDisassembler }
|
||||||
|
|||||||
@ -369,11 +369,11 @@ type
|
|||||||
function GetValue(const AName : string): string;
|
function GetValue(const AName : string): string;
|
||||||
function GetValuePtr(const AName: string): TPCharWithLen;
|
function GetValuePtr(const AName: string): TPCharWithLen;
|
||||||
public
|
public
|
||||||
constructor Create(const AResultValues: String);
|
constructor Create(const AResultValues: String); overload;
|
||||||
constructor Create(const AResultValues: TPCharWithLen);
|
constructor Create(const AResultValues: TPCharWithLen); overload;
|
||||||
constructor Create(AResult: TGDBMIExecResult);
|
constructor Create(AResult: TGDBMIExecResult); overload;
|
||||||
constructor Create(const AResultValues: String; const APath: array of String);
|
constructor Create(const AResultValues: String; const APath: array of String); overload;
|
||||||
constructor Create(AResult: TGDBMIExecResult; const APath: array of String);
|
constructor Create(AResult: TGDBMIExecResult; const APath: array of String); overload;
|
||||||
procedure Delete(AIndex: Integer);
|
procedure Delete(AIndex: Integer);
|
||||||
procedure Init(const AResultValues: String);
|
procedure Init(const AResultValues: String);
|
||||||
procedure Init(AResultValues: PChar; ALength: Integer);
|
procedure Init(AResultValues: PChar; ALength: Integer);
|
||||||
@ -395,6 +395,7 @@ type
|
|||||||
FNameValueList: TGDBMINameValueList;
|
FNameValueList: TGDBMINameValueList;
|
||||||
procedure PreParse; virtual; abstract;
|
procedure PreParse; virtual; abstract;
|
||||||
public
|
public
|
||||||
|
constructor Create;
|
||||||
constructor Create(const AResultValues: String);
|
constructor Create(const AResultValues: String);
|
||||||
constructor Create(AResult: TGDBMIExecResult);
|
constructor Create(AResult: TGDBMIExecResult);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -419,30 +420,6 @@ type
|
|||||||
property Addr: TDBGPtr read FAddr;
|
property Addr: TDBGPtr read FAddr;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGDBMIDisassembleResultList }
|
|
||||||
|
|
||||||
TGDBMIDisassembleResultList = class(TGDBMINameValueBasedList)
|
|
||||||
private
|
|
||||||
FCount: Integer;
|
|
||||||
FHasSourceInfo: Boolean;
|
|
||||||
FItems: array of record
|
|
||||||
AsmEntry: TPCharWithLen;
|
|
||||||
SrcFile: TPCharWithLen;
|
|
||||||
SrcLine: TPCharWithLen;
|
|
||||||
ParsedInfo: TDisassemblerEntry;
|
|
||||||
end;
|
|
||||||
function GetItem(Index: Integer): PDisassemblerEntry;
|
|
||||||
procedure ParseItem(Index: Integer);
|
|
||||||
procedure SetCount(const AValue: Integer);
|
|
||||||
procedure SetItem(Index: Integer; const AValue: PDisassemblerEntry);
|
|
||||||
protected
|
|
||||||
procedure PreParse; override;
|
|
||||||
public
|
|
||||||
property Count: Integer read FCount write SetCount;
|
|
||||||
property HasSourceInfo: Boolean read FHasSourceInfo;
|
|
||||||
property Item[Index: Integer]: PDisassemblerEntry read GetItem write SetItem;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{%endregion *^^^* TGDBMINameValueList and Parsers *^^^* }
|
{%endregion *^^^* TGDBMINameValueList and Parsers *^^^* }
|
||||||
|
|
||||||
{%region ***** TGDBMIDebuggerCommands ***** }
|
{%region ***** TGDBMIDebuggerCommands ***** }
|
||||||
@ -887,6 +864,81 @@ const
|
|||||||
DAssBytesPerCommandMax = 24; // Max possible len. Only used for up to 5 lines
|
DAssBytesPerCommandMax = 24; // Max possible len. Only used for up to 5 lines
|
||||||
type
|
type
|
||||||
|
|
||||||
|
{ TGDBMIDisassembleResultList }
|
||||||
|
|
||||||
|
TGDBMIDisassembleResultList = class(TGDBMINameValueBasedList)
|
||||||
|
private
|
||||||
|
FCount: Integer;
|
||||||
|
FHasSourceInfo: Boolean;
|
||||||
|
FItems: array of record
|
||||||
|
AsmEntry: TPCharWithLen;
|
||||||
|
SrcFile: TPCharWithLen;
|
||||||
|
SrcLine: TPCharWithLen;
|
||||||
|
ParsedInfo: TDisassemblerEntry;
|
||||||
|
end;
|
||||||
|
HasItemPointerList: Boolean;
|
||||||
|
ItemPointerList: Array of PDisassemblerEntry;
|
||||||
|
function GetItem(Index: Integer): PDisassemblerEntry;
|
||||||
|
function GetLastItem: PDisassemblerEntry;
|
||||||
|
procedure ParseItem(Index: Integer);
|
||||||
|
procedure SetCount(const AValue: Integer);
|
||||||
|
procedure SetItem(Index: Integer; const AValue: PDisassemblerEntry);
|
||||||
|
procedure SetLastItem(const AValue: PDisassemblerEntry);
|
||||||
|
protected
|
||||||
|
procedure PreParse; override;
|
||||||
|
public
|
||||||
|
property Count: Integer read FCount write SetCount;
|
||||||
|
property HasSourceInfo: Boolean read FHasSourceInfo;
|
||||||
|
property Item[Index: Integer]: PDisassemblerEntry read GetItem write SetItem;
|
||||||
|
property LastItem: PDisassemblerEntry read GetLastItem write SetLastItem;
|
||||||
|
function SortByAddress: Boolean;
|
||||||
|
public
|
||||||
|
// only valid as long a src object exists, and not modified
|
||||||
|
constructor CreateSubList(ASource: TGDBMIDisassembleResultList; AStartIdx, ACount: Integer);
|
||||||
|
procedure InitSubList(ASource: TGDBMIDisassembleResultList; AStartIdx, ACount: Integer);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TGDBMIDisassembleResultFunctionIterator }
|
||||||
|
|
||||||
|
TGDBMIDisassembleResultFunctionIterator = class
|
||||||
|
private
|
||||||
|
FCurIdx: Integer;
|
||||||
|
FIndexOfLocateAddress: Integer;
|
||||||
|
FOffsetOfLocateAddress: Integer;
|
||||||
|
FIndexOfCounterAddress: Integer;
|
||||||
|
FList: TGDBMIDisassembleResultList;
|
||||||
|
FStartedAtIndex: Integer;
|
||||||
|
FStartIdx, FMaxIdx: Integer;
|
||||||
|
FIgnoreLast: Boolean;
|
||||||
|
FLastSubListEndAddr: TDBGPtr;
|
||||||
|
FAddressToLocate, FAddForLineAfterCounter: TDBGPtr;
|
||||||
|
public
|
||||||
|
constructor Create(AList: TGDBMIDisassembleResultList; AStartIdx: Integer;
|
||||||
|
AIgnoreLast: Boolean;
|
||||||
|
ALastSubListEndAddr: TDBGPtr;
|
||||||
|
AnAddressToLocate, AnAddForLineAfterCounter: TDBGPtr);
|
||||||
|
function EOL: Boolean;
|
||||||
|
function NextSubList(var AResultList: TGDBMIDisassembleResultList): Boolean;
|
||||||
|
|
||||||
|
// Current SubList
|
||||||
|
function IsFirstSubList: Boolean;
|
||||||
|
function CurrentFixedAddr: TDBGPtr; // Addr[0] - Offs[0]
|
||||||
|
// About the next SubList
|
||||||
|
function NextStartAddr: TDBGPtr;
|
||||||
|
function NextStartOffs: Integer;
|
||||||
|
// Overall
|
||||||
|
function CountLinesAfterCounterAddr: Integer; // count up to Startof Current SubList
|
||||||
|
|
||||||
|
property CurrentIndex: Integer read FCurIdx;
|
||||||
|
property NextIndex: Integer read FStartIdx;
|
||||||
|
|
||||||
|
property StartedAtIndex: Integer read FStartedAtIndex;
|
||||||
|
property IndexOfLocateAddress: Integer read FIndexOfLocateAddress;
|
||||||
|
property OffsetOfLocateAddress: Integer read FOffsetOfLocateAddress;
|
||||||
|
property IndexOfCounterAddress: Integer read FIndexOfCounterAddress;
|
||||||
|
property List: TGDBMIDisassembleResultList read FList;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerCommandDisassembe }
|
{ TGDBMIDebuggerCommandDisassembe }
|
||||||
|
|
||||||
TGDBMIDisAssAddrRange = record
|
TGDBMIDisAssAddrRange = record
|
||||||
@ -901,7 +953,7 @@ type
|
|||||||
FOnProgress: TNotifyEvent;
|
FOnProgress: TNotifyEvent;
|
||||||
FStartAddr: TDbgPtr;
|
FStartAddr: TDbgPtr;
|
||||||
FKnownRanges: TDBGDisassemblerEntryMap;
|
FKnownRanges: TDBGDisassemblerEntryMap;
|
||||||
FRangeIterator: TMapIterator;
|
FRangeIterator: TDBGDisassemblerEntryMapIterator;
|
||||||
FMemDumpsNeeded: array of TGDBMIDisAssAddrRange;
|
FMemDumpsNeeded: array of TGDBMIDisAssAddrRange;
|
||||||
procedure DoProgress;
|
procedure DoProgress;
|
||||||
protected
|
protected
|
||||||
@ -1223,6 +1275,11 @@ end;
|
|||||||
|
|
||||||
{ TGDBMINameValueBasedList }
|
{ TGDBMINameValueBasedList }
|
||||||
|
|
||||||
|
constructor TGDBMINameValueBasedList.Create;
|
||||||
|
begin
|
||||||
|
FNameValueList := TGDBMINameValueList.Create;
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TGDBMINameValueBasedList.Create(const AResultValues: String);
|
constructor TGDBMINameValueBasedList.Create(const AResultValues: String);
|
||||||
begin
|
begin
|
||||||
FNameValueList := TGDBMINameValueList.Create(AResultValues);
|
FNameValueList := TGDBMINameValueList.Create(AResultValues);
|
||||||
@ -1270,6 +1327,7 @@ begin
|
|||||||
then
|
then
|
||||||
debugln(['WARNING: TGDBMIDisassembleResultList: Unexpected Entries']);
|
debugln(['WARNING: TGDBMIDisassembleResultList: Unexpected Entries']);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
HasItemPointerList := False;
|
||||||
FNameValueList.SetPath('asm_insns');
|
FNameValueList.SetPath('asm_insns');
|
||||||
FCount := 0;
|
FCount := 0;
|
||||||
SetLength(FItems, FNameValueList.Count * 4);
|
SetLength(FItems, FNameValueList.Count * 4);
|
||||||
@ -1327,8 +1385,64 @@ begin
|
|||||||
FreeAndNil(SrcList);
|
FreeAndNil(SrcList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultList.GetLastItem: PDisassemblerEntry;
|
||||||
|
begin
|
||||||
|
if HasItemPointerList
|
||||||
|
then begin
|
||||||
|
Result := ItemPointerList[Count - 1];
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
ParseItem(Count - 1);
|
||||||
|
Result := @FItems[Count - 1].ParsedInfo;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultList.SortByAddress: Boolean;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
Itm1: PDisassemblerEntry;
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
SetLength(ItemPointerList, FCount);
|
||||||
|
for i := 0 to Count - 1 do begin
|
||||||
|
Itm1 := Item[i];
|
||||||
|
j := i - 1;
|
||||||
|
while j >= 0 do begin
|
||||||
|
if ItemPointerList[j]^.Addr > Itm1^.Addr
|
||||||
|
then ItemPointerList[j+1] := ItemPointerList[j]
|
||||||
|
else break;
|
||||||
|
dec(j);
|
||||||
|
end;
|
||||||
|
ItemPointerList[j+1] := Itm1;
|
||||||
|
end;
|
||||||
|
HasItemPointerList := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TGDBMIDisassembleResultList.CreateSubList(ASource: TGDBMIDisassembleResultList;
|
||||||
|
AStartIdx, ACount: Integer);
|
||||||
|
begin
|
||||||
|
Create;
|
||||||
|
InitSubList(ASource, AStartIdx, ACount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIDisassembleResultList.InitSubList(ASource: TGDBMIDisassembleResultList;
|
||||||
|
AStartIdx, ACount: Integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(ItemPointerList, ACount);
|
||||||
|
FCount := ACount;
|
||||||
|
for i := 0 to ACount - 1 do
|
||||||
|
ItemPointerList[i] := ASource.Item[AStartIdx + i];
|
||||||
|
HasItemPointerList := True;
|
||||||
|
end;
|
||||||
|
|
||||||
function TGDBMIDisassembleResultList.GetItem(Index: Integer): PDisassemblerEntry;
|
function TGDBMIDisassembleResultList.GetItem(Index: Integer): PDisassemblerEntry;
|
||||||
begin
|
begin
|
||||||
|
if HasItemPointerList
|
||||||
|
then begin
|
||||||
|
Result := ItemPointerList[Index];
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
ParseItem(Index);
|
ParseItem(Index);
|
||||||
Result := @FItems[Index].ParsedInfo;
|
Result := @FItems[Index].ParsedInfo;
|
||||||
end;
|
end;
|
||||||
@ -1365,10 +1479,158 @@ end;
|
|||||||
procedure TGDBMIDisassembleResultList.SetItem(Index: Integer;
|
procedure TGDBMIDisassembleResultList.SetItem(Index: Integer;
|
||||||
const AValue: PDisassemblerEntry);
|
const AValue: PDisassemblerEntry);
|
||||||
begin
|
begin
|
||||||
|
if HasItemPointerList
|
||||||
|
then begin
|
||||||
|
ItemPointerList[Index]^ := AValue^;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
FItems[Index].ParsedInfo := AValue^;
|
FItems[Index].ParsedInfo := AValue^;
|
||||||
FItems[Index].AsmEntry.Ptr := nil;
|
FItems[Index].AsmEntry.Ptr := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIDisassembleResultList.SetLastItem(const AValue: PDisassemblerEntry);
|
||||||
|
begin
|
||||||
|
if HasItemPointerList
|
||||||
|
then begin
|
||||||
|
ItemPointerList[Count - 1]^ := AValue^;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
FItems[Count - 1].ParsedInfo := AValue^;
|
||||||
|
FItems[Count - 1].AsmEntry.Ptr := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TGDBMIDisassembleResultFunctionIterator }
|
||||||
|
|
||||||
|
constructor TGDBMIDisassembleResultFunctionIterator.Create(AList: TGDBMIDisassembleResultList;
|
||||||
|
AStartIdx: Integer; AIgnoreLast: Boolean; ALastSubListEndAddr: TDBGPtr;
|
||||||
|
AnAddressToLocate, AnAddForLineAfterCounter: TDBGPtr);
|
||||||
|
begin
|
||||||
|
FList := AList;
|
||||||
|
FStartedAtIndex := AStartIdx;
|
||||||
|
FStartIdx := AStartIdx;
|
||||||
|
FIgnoreLast := AIgnoreLast;
|
||||||
|
FLastSubListEndAddr := ALastSubListEndAddr;
|
||||||
|
FAddressToLocate := AnAddressToLocate;
|
||||||
|
FAddForLineAfterCounter := AnAddForLineAfterCounter;
|
||||||
|
FMaxIdx := FList.Count - 1;
|
||||||
|
if FIgnoreLast
|
||||||
|
then begin
|
||||||
|
FLastSubListEndAddr := FList.Item[FMaxIdx]^.Addr;
|
||||||
|
dec(FMaxIdx);
|
||||||
|
end;
|
||||||
|
if FStartIdx > FMaxIdx
|
||||||
|
then raise Exception.Create('internal error');
|
||||||
|
FIndexOfLocateAddress := 1;
|
||||||
|
FOffsetOfLocateAddress := -1;
|
||||||
|
FIndexOfCounterAddress := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.EOL: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FStartIdx > FMaxIdx ;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.NextSubList
|
||||||
|
(var AResultList: TGDBMIDisassembleResultList): Boolean;
|
||||||
|
var
|
||||||
|
WasBeforeStart: Boolean;
|
||||||
|
HasPrcName: Boolean;
|
||||||
|
PrcBaseAddr: TDBGPtr;
|
||||||
|
Itm: PDisassemblerEntry;
|
||||||
|
NextIdx: Integer;
|
||||||
|
HasLocate: Boolean;
|
||||||
|
begin
|
||||||
|
FCurIdx := FStartIdx;
|
||||||
|
if FStartIdx > FMaxIdx
|
||||||
|
then raise Exception.Create('internal error');
|
||||||
|
|
||||||
|
(* The name may change in the middle of a function. Check for either:
|
||||||
|
- change between no-name and has-name
|
||||||
|
- change of the base-address (addr-offset), if the offset is valid (if has-name)
|
||||||
|
*)
|
||||||
|
HasPrcName := FList.Item[FStartIdx]^.FuncName <> ''; // can use offsets
|
||||||
|
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$ENDIF} // Overflow is allowed to occur
|
||||||
|
PrcBaseAddr := FList.Item[FStartIdx]^.Addr - FList.Item[FStartIdx]^.Offset;
|
||||||
|
{$POP}
|
||||||
|
|
||||||
|
WasBeforeStart := FList.Item[FStartIdx]^.Addr < FAddressToLocate;
|
||||||
|
HasLocate := False;
|
||||||
|
|
||||||
|
NextIdx := FStartIdx + 1;
|
||||||
|
while NextIdx <= FMaxIdx do
|
||||||
|
begin
|
||||||
|
Itm := FList.Item[NextIdx];
|
||||||
|
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$ENDIF} // Overflow is allowed to occur
|
||||||
|
// Also check the next statement after PrcName.
|
||||||
|
// If it has FOffsetOfLocateAddress > 0, then FAddressToLocate is in current block, but not matched
|
||||||
|
if (Itm^.Addr = FAddressToLocate)
|
||||||
|
then begin
|
||||||
|
FIndexOfLocateAddress := NextIdx;
|
||||||
|
FOffsetOfLocateAddress := 0;
|
||||||
|
WasBeforeStart := False;
|
||||||
|
HasLocate := True;
|
||||||
|
end
|
||||||
|
else if WasBeforeStart and (Itm^.Addr > FAddressToLocate)
|
||||||
|
then begin
|
||||||
|
FIndexOfLocateAddress := NextIdx - 1;
|
||||||
|
FOffsetOfLocateAddress := FAddressToLocate - FList.Item[NextIdx-1]^.Addr;
|
||||||
|
WasBeforeStart := False;
|
||||||
|
HasLocate := True;
|
||||||
|
end;
|
||||||
|
if (Itm^.Addr = FAddForLineAfterCounter)
|
||||||
|
or ((Itm^.Addr > FAddForLineAfterCounter) and (FIndexOfCounterAddress < 0))
|
||||||
|
then FIndexOfCounterAddress := NextIdx;
|
||||||
|
|
||||||
|
if (HasPrcName <> (Itm^.FuncName <> ''))
|
||||||
|
or (HasPrcName and (PrcBaseAddr <> Itm^.Addr - Itm^.Offset))
|
||||||
|
then break;
|
||||||
|
{$POP}
|
||||||
|
|
||||||
|
inc(NextIdx);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if AResultList = nil
|
||||||
|
then AResultList := TGDBMIDisassembleResultList.CreateSubList(FList, FStartIdx, NextIdx - FStartIdx)
|
||||||
|
else AResultList.InitSubList(FList, FStartIdx, NextIdx - FStartIdx);
|
||||||
|
FStartIdx := NextIdx;
|
||||||
|
|
||||||
|
// Does the next address look good?
|
||||||
|
// And is AStartAddrHit ok
|
||||||
|
Result := ((NextIdx > FMaxIdx) or (FList.Item[NextIdx]^.Offset = 0))
|
||||||
|
and ( (not HasLocate) or ((FIndexOfLocateAddress < 0) or (FOffsetOfLocateAddress = 0)) );
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.IsFirstSubList: Boolean;
|
||||||
|
begin
|
||||||
|
Result := FStartedAtIndex = FStartIdx;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.CountLinesAfterCounterAddr: Integer;
|
||||||
|
begin
|
||||||
|
Result := -1;
|
||||||
|
if FIndexOfCounterAddress >= 0 then
|
||||||
|
Result := CurrentIndex - IndexOfCounterAddress - 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.CurrentFixedAddr: TDBGPtr;
|
||||||
|
begin
|
||||||
|
Result := FList.Item[CurrentIndex]^.Addr - FList.Item[CurrentIndex]^.Offset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.NextStartAddr: TDBGPtr;
|
||||||
|
begin
|
||||||
|
if NextIndex <= FMaxIdx
|
||||||
|
then Result := FList.Item[NextIndex]^.Addr
|
||||||
|
else Result := FLastSubListEndAddr;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGDBMIDisassembleResultFunctionIterator.NextStartOffs: Integer;
|
||||||
|
begin
|
||||||
|
if NextIndex <= FMaxIdx
|
||||||
|
then Result := FList.Item[NextIndex]^.Offset
|
||||||
|
else Result := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGDBMIMemoryDumpResultList }
|
{ TGDBMIMemoryDumpResultList }
|
||||||
|
|
||||||
function TGDBMIMemoryDumpResultList.GetItemNum(Index: Integer): Integer;
|
function TGDBMIMemoryDumpResultList.GetItemNum(Index: Integer): Integer;
|
||||||
@ -1557,43 +1819,6 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
else Result := TGDBMIMemoryDumpResultList.Create(R);
|
else Result := TGDBMIMemoryDumpResultList.Create(R);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function GetRangeForAddr(AnAddr: TDBGPtr; APrevious: Boolean = True): TDBGDisassemblerEntryRange;
|
|
||||||
begin
|
|
||||||
Result := nil;
|
|
||||||
if not FRangeIterator.Locate(AnAddr)
|
|
||||||
then if not FRangeIterator.BOM
|
|
||||||
then FRangeIterator.Previous;
|
|
||||||
|
|
||||||
if FRangeIterator.BOM
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
FRangeIterator.GetData(Result);
|
|
||||||
if (not APrevious) and not(Result.ContainsAddr(AnAddr))
|
|
||||||
then Result := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetNextRange: TDBGDisassemblerEntryRange;
|
|
||||||
begin
|
|
||||||
Result := nil;
|
|
||||||
if FRangeIterator.EOM
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
FRangeIterator.Next;
|
|
||||||
if not FRangeIterator.EOM
|
|
||||||
then FRangeIterator.GetData(Result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetPrevRange: TDBGDisassemblerEntryRange;
|
|
||||||
begin
|
|
||||||
Result := nil;
|
|
||||||
if FRangeIterator.BOM
|
|
||||||
then exit;
|
|
||||||
|
|
||||||
FRangeIterator.Previous;
|
|
||||||
if not FRangeIterator.BOM
|
|
||||||
then FRangeIterator.GetData(Result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function AdjustToKnowFunctionStart(var AStartAddr: TDbgPtr): Boolean;
|
function AdjustToKnowFunctionStart(var AStartAddr: TDbgPtr): Boolean;
|
||||||
var
|
var
|
||||||
DisAssList: TGDBMIDisassembleResultList;
|
DisAssList: TGDBMIDisassembleResultList;
|
||||||
@ -1844,13 +2069,12 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
StopAfterAddress: TDBGPtr; StopAfterNumLines: Integer
|
StopAfterAddress: TDBGPtr; StopAfterNumLines: Integer
|
||||||
): Boolean;
|
): Boolean;
|
||||||
var
|
var
|
||||||
DisAssList, DisAssListNew, DisAssListWithSrc: TGDBMIDisassembleResultList;
|
DisAssIterator: TGDBMIDisassembleResultFunctionIterator;
|
||||||
NextProcIdx, StartIdx, StartOffs: Integer;
|
DisAssList, DisAssListCurrentSub, DisAssListWithSrc: TGDBMIDisassembleResultList;
|
||||||
i, j, Cnt, InitialIndex, GotLinesAfter: Integer;
|
i, Cnt: Integer;
|
||||||
NewRange: TDBGDisassemblerEntryRange;
|
NewRange: TDBGDisassemblerEntryRange;
|
||||||
NextProcAddr: TDBGPtr;
|
|
||||||
OrigLastAddress, OrigFirstAddress: TDBGPtr;
|
OrigLastAddress, OrigFirstAddress: TDBGPtr;
|
||||||
FirstLoopRun, BlockOk, GotFullDisAss: Boolean;
|
BlockOk, GotFullDisAss: Boolean;
|
||||||
s: String;
|
s: String;
|
||||||
Itm: TDisassemblerEntry;
|
Itm: TDisassemblerEntry;
|
||||||
begin
|
begin
|
||||||
@ -1879,8 +2103,9 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
*)
|
*)
|
||||||
Result := False;
|
Result := False;
|
||||||
DisAssList := nil;
|
DisAssList := nil;
|
||||||
DisAssListNew := nil;
|
DisAssListCurrentSub := nil;
|
||||||
DisAssListWithSrc := nil;
|
DisAssListWithSrc := nil;
|
||||||
|
DisAssIterator := nil;
|
||||||
OrigLastAddress := ALastAddr;
|
OrigLastAddress := ALastAddr;
|
||||||
OrigFirstAddress := AFirstAddr;
|
OrigFirstAddress := AFirstAddr;
|
||||||
|
|
||||||
@ -1891,24 +2116,26 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
if DiscardAtStart
|
if DiscardAtStart
|
||||||
then StartAddr := StartAddr - 5 * DAssBytesPerCommandMax;
|
then StartAddr := StartAddr - 5 * DAssBytesPerCommandMax;
|
||||||
|
|
||||||
|
// Adjust ALastAddr
|
||||||
if ALastAddr < AFirstAddr
|
if ALastAddr < AFirstAddr
|
||||||
then begin
|
then begin
|
||||||
ALastAddr := AFirstAddr + 2 * DAssBytesPerCommandMax;
|
ALastAddr := AFirstAddr + 2 * DAssBytesPerCommandMax;
|
||||||
AEndIsKnownStatement := False;
|
AEndIsKnownStatement := False;
|
||||||
end
|
end
|
||||||
else
|
else if not AEndIsKnownStatement
|
||||||
if not AEndIsKnownStatement
|
|
||||||
then ALastAddr := ALastAddr + 2 * DAssBytesPerCommandMax;
|
then ALastAddr := ALastAddr + 2 * DAssBytesPerCommandMax;
|
||||||
|
|
||||||
|
|
||||||
// check if we have an overall source-info
|
// check if we have an overall source-info
|
||||||
// we can only do that, if we know the offset of firstaddr (limit to 15 avg lines, should be enough)
|
// we can only do that, if we know the offset of firstaddr (limit to 15 avg lines, should be enough)
|
||||||
if (AFirstAddrOffs >= 0)
|
if (AFirstAddrOffs >= 0)
|
||||||
then DisAssListWithSrc := ExecDisassmble
|
then DisAssListWithSrc := ExecDisassmble
|
||||||
(AFirstAddr - Min(AFirstAddrOffs, 15 * DAssBytesPerCommandAvg), ALastAddr, True);
|
(AFirstAddr - Min(AFirstAddrOffs, 15 * DAssBytesPerCommandAvg), ALastAddr, True);
|
||||||
GotFullDisAss := (DisAssListWithSrc <> nil) and (DisAssListWithSrc.Count > 0) and DisAssListWithSrc.HasSourceInfo;
|
GotFullDisAss := (DisAssListWithSrc <> nil) and (DisAssListWithSrc.Count > 0) and DisAssListWithSrc.HasSourceInfo;
|
||||||
|
|
||||||
if (DisAssListWithSrc <> nil) and (DisAssListWithSrc.Count > 0) and (not DisAssListWithSrc.HasSourceInfo)
|
if (DisAssListWithSrc <> nil) and (DisAssListWithSrc.Count > 0) and (not DisAssListWithSrc.HasSourceInfo)
|
||||||
then begin
|
then begin
|
||||||
// got data, but no mem dump
|
// got data, but no src info
|
||||||
DisAssList := DisAssListWithSrc;
|
DisAssList := DisAssListWithSrc;
|
||||||
DisAssListWithSrc := nil;
|
DisAssListWithSrc := nil;
|
||||||
end;
|
end;
|
||||||
@ -1918,6 +2145,7 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
if DisAssList = nil
|
if DisAssList = nil
|
||||||
then DisAssList := ExecDisassmble(AFirstAddr, ALastAddr, False);
|
then DisAssList := ExecDisassmble(AFirstAddr, ALastAddr, False);
|
||||||
|
|
||||||
|
|
||||||
Cnt := DisAssList.Count;
|
Cnt := DisAssList.Count;
|
||||||
if Cnt < 2
|
if Cnt < 2
|
||||||
then begin
|
then begin
|
||||||
@ -1957,6 +2185,7 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
AFirstAddr := DisAssList.Item[i]^.Addr;
|
AFirstAddr := DisAssList.Item[i]^.Addr;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
NewRange := TDBGDisassemblerEntryRange.Create;
|
NewRange := TDBGDisassemblerEntryRange.Create;
|
||||||
NewRange.Capacity := Cnt;
|
NewRange.Capacity := Cnt;
|
||||||
if AEndIsKnownStatement
|
if AEndIsKnownStatement
|
||||||
@ -1965,123 +2194,114 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
NewRange.RangeStartAddr := AFirstAddr;
|
NewRange.RangeStartAddr := AFirstAddr;
|
||||||
NewRange.RangeEndAddr := OrigLastAddress;
|
NewRange.RangeEndAddr := OrigLastAddress;
|
||||||
|
|
||||||
InitialIndex := i;
|
DisAssIterator := TGDBMIDisassembleResultFunctionIterator.Create
|
||||||
GotLinesAfter := 0;
|
(DisAssList, i, not AEndIsKnownStatement, ALastAddr, FStartAddr, FEndAddr);
|
||||||
NextProcAddr := 0;
|
|
||||||
while i < Cnt
|
while not DisAssIterator.EOL
|
||||||
do begin
|
do begin
|
||||||
if (StopAfterAddress <> 0) and (GotLinesAfter > StopAfterNumLines) then
|
BlockOk := DisAssIterator.NextSubList(DisAssListCurrentSub);
|
||||||
begin
|
|
||||||
// got enough lines
|
if (StopAfterAddress <> 0)
|
||||||
NewRange.LastEntryEndAddr := NextProcAddr;
|
and (DisAssIterator.CountLinesAfterCounterAddr > StopAfterNumLines) // got enough lines
|
||||||
NewRange.RangeEndAddr := NextProcAddr;
|
// only if the next block is good to go
|
||||||
|
and not ( (not BlockOk) or (DisAssListCurrentSub.Item[0]^.Offset <> 0) or (not GotFullDisAss) )
|
||||||
|
then begin
|
||||||
|
NewRange.LastEntryEndAddr := DisAssIterator.NextStartAddr;
|
||||||
|
NewRange.RangeEndAddr := DisAssIterator.NextStartAddr;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
FirstLoopRun := i = InitialIndex;
|
if (not DisAssIterator.IsFirstSubList) and (DisAssListCurrentSub.Item[0]^.Offset <> 0)
|
||||||
BlockOk := FindProcEnd(DisAssList, i, NextProcIdx, StartIdx, StartOffs, not AEndIsKnownStatement);
|
|
||||||
if (DisAssList.Item[i]^.Addr >= StopAfterAddress)
|
|
||||||
then inc(GotLinesAfter, NextProcIdx - i)
|
|
||||||
else if StartIdx > 0
|
|
||||||
then inc(GotLinesAfter, NextProcIdx - StartIdx - 1);
|
|
||||||
|
|
||||||
if NextProcIdx < Cnt
|
|
||||||
then NextProcAddr := DisAssList.Item[NextProcIdx]^.Addr - DisAssList.Item[NextProcIdx]^.Offset
|
|
||||||
else NextProcAddr := ALastAddr;
|
|
||||||
|
|
||||||
if (not FirstLoopRun) and (DisAssList.Item[i]^.Offset <> 0)
|
|
||||||
then begin
|
then begin
|
||||||
// Current block starts with offset. Adjust and disassemble again
|
// Current block starts with offset. Adjust and disassemble again
|
||||||
// Try with source first, in case it returns dat without source
|
// Try with source first, in case it returns dat without source
|
||||||
if GotFullDisAss
|
if GotFullDisAss
|
||||||
then begin
|
then begin
|
||||||
//get the source-less code as reference
|
//get the source-less code as reference
|
||||||
DisAssListNew := ExecDisassmble(DisAssList.Item[i]^.Addr - DisAssList.Item[i]^.Offset,
|
DisAssListCurrentSub := ExecDisassmble(DisAssIterator.CurrentFixedAddr,
|
||||||
NextProcAddr, False, DisAssListNew);
|
DisAssIterator.NextStartAddr, False, DisAssListCurrentSub);
|
||||||
CopyToRange(DisAssListNew, NewRange, 0, DisAssListNew.Count, DisAssListWithSrc);
|
CopyToRange(DisAssListCurrentSub, NewRange, 0, DisAssListCurrentSub.Count, DisAssListWithSrc);
|
||||||
i := NextProcIdx;
|
Result := Result or (DisAssListCurrentSub.Count > 0);
|
||||||
Result := True;
|
|
||||||
continue;
|
continue;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
DisAssListWithSrc := ExecDisassmble(DisAssList.Item[i]^.Addr - DisAssList.Item[i]^.Offset,
|
// Try source first
|
||||||
NextProcAddr, True, DisAssListWithSrc);
|
DisAssListWithSrc := ExecDisassmble(DisAssIterator.CurrentFixedAddr,
|
||||||
|
DisAssIterator.NextStartAddr, True, DisAssListWithSrc);
|
||||||
if (DisAssListWithSrc.Count > 0) and (not DisAssListWithSrc.HasSourceInfo)
|
if (DisAssListWithSrc.Count > 0) and (not DisAssListWithSrc.HasSourceInfo)
|
||||||
then begin
|
then begin
|
||||||
// no source avail, but got data
|
// no source avail, but got data
|
||||||
CopyToRange(DisAssListWithSrc, NewRange, 0, DisAssListWithSrc.Count);
|
CopyToRange(DisAssListWithSrc, NewRange, 0, DisAssListWithSrc.Count);
|
||||||
i := NextProcIdx;
|
|
||||||
Result := True;
|
Result := True;
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
//get the source-less code as reference
|
//get the source-less code as reference
|
||||||
DisAssListNew := ExecDisassmble(DisAssList.Item[i]^.Addr - DisAssList.Item[i]^.Offset,
|
DisAssListCurrentSub := ExecDisassmble(DisAssIterator.CurrentFixedAddr,
|
||||||
NextProcAddr, False, DisAssListNew);
|
DisAssIterator.NextStartAddr, False, DisAssListCurrentSub);
|
||||||
CopyToRange(DisAssListNew, NewRange, 0, DisAssListNew.Count, DisAssListWithSrc);
|
CopyToRange(DisAssListCurrentSub, NewRange, 0, DisAssListCurrentSub.Count, DisAssListWithSrc);
|
||||||
i := NextProcIdx;
|
Result := Result or (DisAssListCurrentSub.Count > 0);
|
||||||
Result := True;
|
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Todo: Check for wrong start stmnt offset
|
// Todo: Check for wrong start stmnt offset
|
||||||
if not BlockOk
|
if not BlockOk
|
||||||
and (NextProcIdx < Cnt) and (DisAssList.Item[NextProcIdx]^.Offset <> 0)
|
and (DisAssIterator.NextStartOffs <> 0)
|
||||||
then begin
|
then begin
|
||||||
// overlap into next proc
|
// overlap into next proc
|
||||||
{$IFDEF DBG_VERBOSE}
|
{$IFDEF DBG_VERBOSE}
|
||||||
debugln(['WARNING: FindProcEnd found an overlap at block end: FromIdx=', i,' NextIdx=', NextProcIdx, ' StartIdx=', StartIdx, ' StartOffs=',StartOffs ]);
|
debugln(['WARNING: FindProcEnd found an overlap at block end: FromIdx=', DisAssIterator.CurrentIndex,
|
||||||
|
' NextIdx=', DisAssIterator.NextIndex, ' StartIdx=', DisAssIterator.IndexOfLocateAddress, ' StartOffs=', DisAssIterator.OffsetOfLocateAddress]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
j := DisAssList.Item[NextProcIdx]^.Offset;
|
s := DisAssListCurrentSub.LastItem^.Dump;
|
||||||
s := DisAssList.Item[NextProcIdx-1]^.Dump;
|
s := copy(s, 1, Max(0, length(s) - DisAssIterator.NextStartOffs * 2));
|
||||||
s := copy(s, 1, Max(0, length(s) - j*2));
|
|
||||||
if s = ''
|
if s = ''
|
||||||
then s := ' ';
|
then s := ' ';
|
||||||
DisAssList.Item[NextProcIdx-1]^.Dump := s;
|
DisAssListCurrentSub.LastItem^.Dump := s;
|
||||||
DisAssList.Item[NextProcIdx-1]^.Statement := '';
|
DisAssListCurrentSub.LastItem^.Statement := '';
|
||||||
BlockOk := True;
|
BlockOk := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if BlockOk
|
if BlockOk
|
||||||
then begin
|
then begin
|
||||||
// Got a good block
|
// Got a good block
|
||||||
if (DisAssList.Item[i]^.FuncName <> '')
|
if (DisAssListCurrentSub.Item[0]^.FuncName <> '')
|
||||||
then begin
|
then begin
|
||||||
// Try to get source-info (up to NextProcAddr)
|
// Try to get source-info (up to DisAssIterator.NextStartAddr)
|
||||||
// Subtract offset from StartAddress, in case this is the first block
|
// Subtract offset from StartAddress, in case this is the first block
|
||||||
// (we may continue existing data, but src info must be retrieved in full, or may be incomplete)
|
// (we may continue existing data, but src info must be retrieved in full, or may be incomplete)
|
||||||
// If we are in FirstLoopRun, we already tried
|
// If we are in IsFirstSubList, we already tried
|
||||||
if (not GotFullDisAss) and (not FirstLoopRun)
|
if (not GotFullDisAss) and (not DisAssIterator.IsFirstSubList)
|
||||||
then DisAssListWithSrc := ExecDisassmble(DisAssList.Item[i]^.Addr - DisAssList.Item[i]^.Offset,
|
then DisAssListWithSrc := ExecDisassmble(DisAssIterator.CurrentFixedAddr,
|
||||||
NextProcAddr, True, DisAssListWithSrc);
|
DisAssIterator.NextStartAddr, True, DisAssListWithSrc);
|
||||||
// We may have less lines with source, as we stripped padding at the end
|
// We may have less lines with source, as we stripped padding at the end
|
||||||
if (DisAssListWithSrc <> nil) and DisAssListWithSrc.HasSourceInfo
|
if (DisAssListWithSrc <> nil) and DisAssListWithSrc.HasSourceInfo
|
||||||
then begin
|
then begin
|
||||||
CopyToRange(DisAssList, NewRange, i, NextProcIdx - i, DisAssListWithSrc);
|
CopyToRange(DisAssListCurrentSub, NewRange, 0, DisAssListCurrentSub.Count, DisAssListWithSrc);
|
||||||
i := NextProcIdx;
|
Result := Result or (DisAssListCurrentSub.Count > 0);
|
||||||
Result := True;
|
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
CopyToRange(DisAssList, NewRange, i, NextProcIdx - i);
|
CopyToRange(DisAssListCurrentSub, NewRange, 0, DisAssListCurrentSub.Count);
|
||||||
i := NextProcIdx;
|
Result := Result or (DisAssListCurrentSub.Count > 0);
|
||||||
Result := True;
|
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Got a problematic block
|
// Got a problematic block
|
||||||
{$IFDEF DBG_VERBOSE}
|
{$IFDEF DBG_VERBOSE}
|
||||||
debugln(['WARNING: FindProcEnd reported an issue FromIdx=', i,' NextIdx=', NextProcIdx, ' StartIdx=', StartIdx, ' StartOffs=',StartOffs ]);
|
debugln(['WARNING: FindProcEnd reported an issue FromIdx=', DisAssIterator.CurrentIndex,' NextIdx=',
|
||||||
|
DisAssIterator.NextIndex, ' StartIdx=', DisAssIterator.IndexOfLocateAddress, ' StartOffs=', DisAssIterator.OffsetOfLocateAddress]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if DiscardAtStart and (StartIdx >= 0) and (StartOffs <> 0)
|
if DiscardAtStart
|
||||||
|
and (DisAssIterator.IndexOfLocateAddress >= DisAssIterator.CurrentIndex) // in current list
|
||||||
|
and (DisAssIterator.OffsetOfLocateAddress <> 0)
|
||||||
then begin
|
then begin
|
||||||
// FStartAddr is in the middle of a statement. Maybe move the Range?
|
// FStartAddr is in the middle of a statement. Maybe move the Range?
|
||||||
end;
|
end;
|
||||||
|
|
||||||
CopyToRange(DisAssList, NewRange, i, NextProcIdx - i);
|
CopyToRange(DisAssListCurrentSub, NewRange, 0, DisAssListCurrentSub.Count);
|
||||||
i := NextProcIdx;
|
Result := Result or (DisAssListCurrentSub.Count > 0);
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if NewRange.LastEntryEndAddr > NewRange.RangeEndAddr
|
if NewRange.LastEntryEndAddr > NewRange.RangeEndAddr
|
||||||
@ -2120,8 +2340,9 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
FKnownRanges.AddRange(NewRange); // NewRange is now owned by FKnownRanges
|
FKnownRanges.AddRange(NewRange); // NewRange is now owned by FKnownRanges
|
||||||
NewRange := nil;
|
NewRange := nil;
|
||||||
|
|
||||||
|
FreeAndNil(DisAssIterator);
|
||||||
FreeAndNil(DisAssList);
|
FreeAndNil(DisAssList);
|
||||||
FreeAndNil(DisAssListNew);
|
FreeAndNil(DisAssListCurrentSub);
|
||||||
FreeAndNil(DisAssListWithSrc);
|
FreeAndNil(DisAssListWithSrc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2136,13 +2357,13 @@ function TGDBMIDebuggerCommandDisassembe.DoExecute: Boolean;
|
|||||||
for i := 0 to length(FMemDumpsNeeded) - 1 do
|
for i := 0 to length(FMemDumpsNeeded) - 1 do
|
||||||
begin
|
begin
|
||||||
FirstAddr := FMemDumpsNeeded[i].FirstAddr;
|
FirstAddr := FMemDumpsNeeded[i].FirstAddr;
|
||||||
Rng := GetRangeForAddr(FirstAddr, True);
|
Rng := FRangeIterator.GetRangeForAddr(FirstAddr, True);
|
||||||
if rng <> nil
|
if rng <> nil
|
||||||
then MemDump := ExecMemDump(FirstAddr, FMemDumpsNeeded[i].LastAddr - FirstAddr, MemDump);
|
then MemDump := ExecMemDump(FirstAddr, FMemDumpsNeeded[i].LastAddr - FirstAddr, MemDump);
|
||||||
while (Rng <> nil) and (Rng.FirstAddr <= FMemDumpsNeeded[i].LastAddr) do
|
while (Rng <> nil) and (Rng.FirstAddr <= FMemDumpsNeeded[i].LastAddr) do
|
||||||
begin
|
begin
|
||||||
AddMemDumpToRange(Rng, MemDump, FMemDumpsNeeded[i].FirstAddr, FMemDumpsNeeded[i].LastAddr);
|
AddMemDumpToRange(Rng, MemDump, FMemDumpsNeeded[i].FirstAddr, FMemDumpsNeeded[i].LastAddr);
|
||||||
Rng := GetNextRange;
|
Rng := FRangeIterator.NextRange;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
FreeAndNil(MemDump);
|
FreeAndNil(MemDump);
|
||||||
@ -2169,7 +2390,7 @@ begin
|
|||||||
// or the rng before (if not to far back)
|
// or the rng before (if not to far back)
|
||||||
TryStartAtOffs := -1;
|
TryStartAtOffs := -1;
|
||||||
DiscardAtStart := False;
|
DiscardAtStart := False;
|
||||||
RngBefore := GetRangeForAddr(FStartAddr, True);
|
RngBefore := FRangeIterator.GetRangeForAddr(FStartAddr, True);
|
||||||
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$R-}{$ENDIF} // Overflow is allowed to occur
|
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$R-}{$ENDIF} // Overflow is allowed to occur
|
||||||
if (RngBefore <> nil)
|
if (RngBefore <> nil)
|
||||||
and (TryStartAt > RngBefore.EntriesPtr[RngBefore.Count - 1]^.Addr)
|
and (TryStartAt > RngBefore.EntriesPtr[RngBefore.Count - 1]^.Addr)
|
||||||
@ -2211,7 +2432,7 @@ begin
|
|||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
RngAfter := GetNextRange;
|
RngAfter := FRangeIterator.NextRange;
|
||||||
// adjust TryEndAt
|
// adjust TryEndAt
|
||||||
if (RngAfter <> nil) and (TryEndAt >= RngAfter.RangeStartAddr)
|
if (RngAfter <> nil) and (TryEndAt >= RngAfter.RangeStartAddr)
|
||||||
then TryEndAt := RngAfter.RangeStartAddr;
|
then TryEndAt := RngAfter.RangeStartAddr;
|
||||||
@ -2226,7 +2447,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// prepare the next range
|
// prepare the next range
|
||||||
RngBefore := GetRangeForAddr(FStartAddr, False);
|
RngBefore := FRangeIterator.GetRangeForAddr(FStartAddr, False);
|
||||||
if (RngBefore = nil)
|
if (RngBefore = nil)
|
||||||
then begin
|
then begin
|
||||||
debugln(['INTERNAL ERROR: (linesafter) Missing the data, that was just disassembled: from ', TryStartAt,' to ', TryEndAt]);
|
debugln(['INTERNAL ERROR: (linesafter) Missing the data, that was just disassembled: from ', TryStartAt,' to ', TryEndAt]);
|
||||||
@ -2239,7 +2460,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Find LinesBefore
|
// Find LinesBefore
|
||||||
RngAfter := GetRangeForAddr(FStartAddr, False);
|
RngAfter := FRangeIterator.GetRangeForAddr(FStartAddr, False);
|
||||||
GotCnt := -1;
|
GotCnt := -1;
|
||||||
while(True)
|
while(True)
|
||||||
do begin
|
do begin
|
||||||
@ -2262,7 +2483,7 @@ begin
|
|||||||
TryEndAt := RngAfter.RangeStartAddr;
|
TryEndAt := RngAfter.RangeStartAddr;
|
||||||
TryStartAt := TryEndAt - 1;
|
TryStartAt := TryEndAt - 1;
|
||||||
// and adjust
|
// and adjust
|
||||||
RngBefore := GetPrevRange;
|
RngBefore := FRangeIterator.PreviousRange;
|
||||||
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$R-}{$ENDIF} // Overflow is allowed to occur
|
{$PUSH}{$IFnDEF DBGMI_WITH_DISASS_OVERFLOW}{$Q-}{$R-}{$ENDIF} // Overflow is allowed to occur
|
||||||
if (RngBefore <> nil)
|
if (RngBefore <> nil)
|
||||||
and (TryStartAt > RngBefore.EntriesPtr[RngBefore.Count - 1]^.Addr)
|
and (TryStartAt > RngBefore.EntriesPtr[RngBefore.Count - 1]^.Addr)
|
||||||
@ -2281,7 +2502,7 @@ begin
|
|||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
RngAfter := GetRangeForAddr(FStartAddr, False);
|
RngAfter := FRangeIterator.GetRangeForAddr(FStartAddr, False);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
DoProgress;
|
DoProgress;
|
||||||
@ -2295,7 +2516,7 @@ constructor TGDBMIDebuggerCommandDisassembe.Create(AOwner: TGDBMIDebugger;
|
|||||||
begin
|
begin
|
||||||
inherited Create(AOwner);
|
inherited Create(AOwner);
|
||||||
FKnownRanges := AKnownRanges;
|
FKnownRanges := AKnownRanges;
|
||||||
FRangeIterator:= TMapIterator.Create(FKnownRanges);
|
FRangeIterator:= TDBGDisassemblerEntryMapIterator.Create(FKnownRanges);
|
||||||
FStartAddr := AStartAddr;
|
FStartAddr := AStartAddr;
|
||||||
FEndAddr := AEndAddr;
|
FEndAddr := AEndAddr;
|
||||||
FLinesBefore := ALinesBefore;
|
FLinesBefore := ALinesBefore;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user