2011-07-04 19:52:53 +00:00
unit frmStackViewUnit;
{$mode delphi}
interface
uses
2019-12-18 12:07:17 +01:00
{$ifdef darwin}
macport,
{$endif}
{$ifdef windows}
windows,
{$endif}
cefuncproc, newkernelhandler, Classes, SysUtils, FileUtil, LResources,
2011-07-04 19:52:53 +00:00
Forms, Controls, Graphics, Dialogs, StdCtrls, Menus, stacktrace2, Clipbrd, ComCtrls,
2023-10-20 17:32:15 +02:00
strutils, frmSelectionlistunit, maps, betterControls, contexthandler;
2011-07-04 19:52:53 +00:00
type
{ TfrmStackView }
TfrmStackView = class( TForm)
2013-11-12 23:44:04 +00:00
ColorDialog1: TColorDialog;
2013-11-12 22:42:47 +00:00
FindDialog1: TFindDialog;
2019-06-05 12:36:47 +02:00
svImageList: TImageList;
2011-07-04 19:52:53 +00:00
lvStack: TListView;
MenuItem1: TMenuItem;
2012-04-06 23:08:22 +00:00
MenuItem2: TMenuItem;
MenuItem3: TMenuItem;
2013-11-12 22:42:47 +00:00
MenuItem4: TMenuItem;
2013-11-12 23:44:04 +00:00
MenuItem5: TMenuItem;
2017-05-16 04:03:58 +02:00
MenuItem6: TMenuItem;
2017-05-15 22:57:21 +02:00
miAddRef: TMenuItem;
2013-11-12 23:44:04 +00:00
miSetColor: TMenuItem;
2013-11-12 22:42:47 +00:00
miFindNext: TMenuItem;
miFind: TMenuItem;
2013-06-09 11:54:30 +00:00
miLockAndTrace: TMenuItem;
2011-07-04 19:52:53 +00:00
miCopyValue: TMenuItem;
miCopySecondary: TMenuItem;
miCopyAddress: TMenuItem;
miAddESP: TMenuItem;
miAddEBP: TMenuItem;
PopupMenu1: TPopupMenu;
2013-11-12 22:42:47 +00:00
procedure FindDialog1Find( Sender: TObject) ;
2011-07-04 19:52:53 +00:00
procedure FormClose( Sender: TObject; var CloseAction: TCloseAction) ;
2013-06-09 11:54:30 +00:00
procedure FormCloseQuery( Sender: TObject; var CanClose: boolean ) ;
2011-07-04 19:52:53 +00:00
procedure FormCreate( Sender: TObject) ;
procedure FormDestroy( Sender: TObject) ;
procedure FormShow( Sender: TObject) ;
2013-11-12 23:44:04 +00:00
procedure lvStackCustomDrawItem( Sender: TCustomListView; Item: TListItem;
State: TCustomDrawState; var DefaultDraw: Boolean ) ;
2011-07-04 19:52:53 +00:00
procedure lvStackDblClick( Sender: TObject) ;
2012-04-06 23:08:22 +00:00
procedure MenuItem3Click( Sender: TObject) ;
2017-05-15 22:57:21 +02:00
procedure miAddRefClick( Sender: TObject) ;
2013-11-12 23:44:04 +00:00
procedure miSetColorClick( Sender: TObject) ;
2013-11-12 22:42:47 +00:00
procedure miFindClick( Sender: TObject) ;
2013-06-09 11:54:30 +00:00
procedure miLockAndTraceClick( Sender: TObject) ;
2011-07-04 19:52:53 +00:00
procedure miAddESPClick( Sender: TObject) ;
procedure miCopyAddressClick( Sender: TObject) ;
2017-05-15 22:57:21 +02:00
procedure PopupMenu1Popup( Sender: TObject) ;
2011-07-04 19:52:53 +00:00
private
{ private declarations }
2023-10-20 17:32:15 +02:00
c: pointer ;
contexthandler: TContextInfo;
2011-07-04 19:52:53 +00:00
stack: pbyte ;
size: integer ;
2013-06-09 11:54:30 +00:00
allocs: tlist;
2013-11-12 23:44:04 +00:00
colors: TMap;
2017-05-15 22:57:21 +02:00
StackReference: ptruint;
2011-07-04 19:52:53 +00:00
public
{ public declarations }
2023-10-20 17:32:15 +02:00
procedure SetContextPointer( c: pointer ; stack: pbyte ; size: integer ) ;
2011-07-04 19:52:53 +00:00
end ;
var
frmStackView: TfrmStackView;
2014-02-13 22:40:50 +00:00
resourcestring
rsTheStructuresListIsBroken = 'The structures list is broken' ;
rsNewWindow = '<New window>' ;
rsLockAndAddToStructureDissect = 'Lock and add to structure dissect' ;
rsSelectTheStructureDissectWindowYouWishToAddThisReg = 'Select the structure'
+ ' dissect window you wish to add this region to' ;
2015-10-10 13:21:06 +02:00
rsSVThisStackViewWindowHasAllocatedStackSnapshotsEtc = 'This stackview window has allocated stack snapshots in the target process. Do you wish to free them?' ;
2014-02-13 22:40:50 +00:00
2015-10-13 00:48:24 +02:00
implementation
uses MemoryBrowserFormUnit, StructuresFrm2, frmstacktraceunit, processhandlerunit;
2011-07-04 19:52:53 +00:00
procedure TfrmStackView. miAddESPClick( Sender: TObject) ;
begin
SetContextPointer( c, stack, size) ;
end ;
procedure TfrmStackView. miCopyAddressClick( Sender: TObject) ;
var i: integer ;
s: tstringlist;
part: integer ;
begin
part: = TMenuItem( sender) . Tag;
s: = tstringlist. create;
try
for i: = 0 to lvstack. items. count- 1 do
begin
if lvstack. items[ i] . Selected then
begin
2017-05-16 04:03:58 +02:00
case part of
0 : s. add( lvstack. items[ i] . caption) ;
1 , 2 : s. add( lvstack. items[ i] . SubItems[ part- 1 ] ) ;
3 : s. add( PadRight( lvstack. items[ i] . caption, 2 0 ) + ' - ' + PadRight( lvstack. items[ i] . SubItems[ 0 ] , 2 0 ) + ' - ' + lvstack. items[ i] . SubItems[ 1 ] ) ;
end ;
2011-07-04 19:52:53 +00:00
end ;
end ;
Clipboard. AsText: = s. text ;
finally
s. free;
end ;
end ;
2017-05-15 22:57:21 +02:00
procedure TfrmStackView. PopupMenu1Popup( Sender: TObject) ;
var
x: ptruint;
2023-10-20 17:32:15 +02:00
ch: TContextInfo;
2017-05-15 22:57:21 +02:00
begin
2023-10-20 17:32:15 +02:00
ch: = getBestContextHandler;
miAddESP. Caption: = '(' + ch. StackPointerRegister^ . name + ')' ;
miAddEBP. Caption: = '(' + ch. FramePointerRegister^ . name + ')' ;
2019-01-28 00:52:39 +01:00
2017-05-15 22:57:21 +02:00
if lvStack. selected< > nil then
begin
x: = ptruint( lvstack. selected. data) ;
miAddRef. caption: = format( '(ref+*) Ref will be %x' , [ x] ) ;
end ;
2019-01-28 00:52:39 +01:00
2023-10-20 17:32:15 +02:00
miAddEBP. Enabled: = ch. FramePointerRegister^ . getValue( c) < > 0 ;
2019-01-28 00:52:39 +01:00
if not miAddEBP. Enabled and miAddEBP. Checked then miAddESP. Checked: = true ;
2017-05-15 22:57:21 +02:00
end ;
2011-07-04 19:52:53 +00:00
procedure TfrmStackView. lvStackDblClick( Sender: TObject) ;
var p: tpoint;
a: ptruint;
begin
if lvstack. Selected< > nil then
begin
//get tht column that is clicked
p: = lvStack. ScreenToClient( mouse. CursorPos) ;
a: = ptruint( lvstack. selected. data) ;
if p. x> lvStack. Column[ 0 ] . Width then
a: = StrToQWord( '$' + lvstack. Selected. SubItems[ 0 ] ) ;
if not MemoryBrowser. visible then
MemoryBrowser. visible: = true ;
if p. x> lvStack. column[ 1 ] . width then
MemoryBrowser. disassemblerview. SelectedAddress: = a
else
MemoryBrowser. hexview. address: = a;
end ;
end ;
2012-04-06 23:08:22 +00:00
procedure TfrmStackView. MenuItem3Click( Sender: TObject) ;
var
i: integer ;
s: tstringlist;
f: TfrmSelectionList;
structurefrm: TfrmStructures2;
new: boolean ;
begin
//find out which data dissect windows are open
s: = tstringlist. create;
2012-04-29 21:47:47 +00:00
if frmStructures2= nil then
2014-02-13 22:40:50 +00:00
raise exception. create( rsTheStructuresListIsBroken) ;
2012-04-29 21:47:47 +00:00
2012-04-06 23:08:22 +00:00
for i: = 0 to frmStructures2. Count- 1 do
2012-04-29 21:47:47 +00:00
s. add( TfrmStructures2( frmStructures2[ i] ) . Caption) ;
2012-04-06 23:08:22 +00:00
2014-02-13 22:40:50 +00:00
s. add( rsNewWindow) ;
2012-04-06 23:08:22 +00:00
f: = TfrmSelectionList. Create( self, s) ;
2014-02-13 22:40:50 +00:00
f. caption: = rsLockAndAddToStructureDissect;
f. label1. Caption: = rsSelectTheStructureDissectWindowYouWishToAddThisReg;
2012-04-06 23:08:22 +00:00
if f. showmodal= mrok then
begin
2013-04-01 20:15:13 +00:00
if f. itemindex= - 1 then f. itemindex: = 0 ;
2012-04-06 23:08:22 +00:00
if f. itemindex> = frmStructures2. Count then //new window
begin
structurefrm: = tfrmstructures2. create( application) ;
structurefrm. show;
end
else
structurefrm: = TfrmStructures2( frmStructures2[ f. itemindex] ) ;
//add this esp (c.rsp/esp) as locked address
2023-10-20 17:32:15 +02:00
structurefrm. addLockedAddress( contexthandler. StackPointerRegister^ . getValue( c) , stack, size) ;
2012-04-06 23:08:22 +00:00
structurefrm. show;
if structurefrm. mainStruct= nil then //if no structure is selected define it then
2013-04-01 20:15:13 +00:00
structurefrm. DefineNewStructure( size) ;
2012-04-06 23:08:22 +00:00
end ;
end ;
2017-05-16 04:03:58 +02:00
2017-05-15 22:57:21 +02:00
procedure TfrmStackView. miAddRefClick( Sender: TObject) ;
begin
if lvStack. Selected< > nil then
begin
StackReference: = ptruint( lvstack. selected. data) ;
SetContextPointer( c, stack, size) ;
end
else
miAddESP. Checked: = true ;
end ;
2013-11-12 23:44:04 +00:00
procedure TfrmStackView. miSetColorClick( Sender: TObject) ;
var i: integer ;
a: ptruint;
2016-08-25 21:31:09 +02:00
oldc, c: tcolor;
2013-11-12 23:44:04 +00:00
begin
if lvStack. selected< > nil then
begin
a: = ptruint( lvStack. Selected. Data) ;
if colors. GetData( a, c) then
colordialog1. Color: = c;
if ColorDialog1. execute then
begin
c: = colordialog1. Color;
for i: = 0 to lvstack. items. count- 1 do
begin
if lvstack. items[ i] . Selected then
begin
a: = ptruint( lvStack. items[ i] . Data) ;
2016-08-25 21:31:09 +02:00
if colors. HasId( a) then
colors. SetData( a, c)
else
colors. Add( a, c) ;
2013-11-12 23:44:04 +00:00
end ;
end ;
end ;
2016-08-25 21:31:09 +02:00
lvStack. Refresh;
2013-11-12 23:44:04 +00:00
lvStack. Repaint;
end ;
end ;
2013-11-12 22:42:47 +00:00
procedure TfrmStackView. miFindClick( Sender: TObject) ;
begin
2016-09-24 14:46:03 +02:00
2013-11-12 22:42:47 +00:00
finddialog1. execute;
end ;
2013-06-09 11:54:30 +00:00
procedure TfrmStackView. miLockAndTraceClick( Sender: TObject) ;
var
2014-05-11 03:08:36 +00:00
x: PtrUInt;
2013-06-09 11:54:30 +00:00
alloc: pointer ;
f: TfrmStacktrace;
begin
2023-10-20 17:32:15 +02:00
if contexthandler= nil then
contexthandler: = getBestContextHandler;
2013-06-09 11:54:30 +00:00
alloc: = VirtualAllocEx( processhandle, nil , size+ 1 , MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE) ;
if alloc< > nil then
begin
if allocs= nil then
allocs: = tlist. create;
//copy the original bytes to the copy
WriteProcessMemory( processhandle, pointer( alloc) , stack, size, x) ;
allocs. Add( alloc) ;
f: = TfrmStacktrace. create( application) ;
2023-10-20 17:32:15 +02:00
f. shadowstacktrace( c, alloc, size) ;
2013-06-09 11:54:30 +00:00
f. show;
end ;
end ;
2011-07-04 19:52:53 +00:00
procedure TfrmStackView. FormDestroy( Sender: TObject) ;
begin
2013-11-12 23:44:04 +00:00
colors. Free;
2011-07-04 19:52:53 +00:00
end ;
procedure TfrmStackView. FormShow( Sender: TObject) ;
2021-01-24 22:37:53 +01:00
var
x: array of integer ;
w: integer ;
2011-07-04 19:52:53 +00:00
begin
setlength( x, 3 ) ;
if LoadFormPosition( self, x) then
begin
if length( x) > = 3 then
begin
lvstack. Column[ 0 ] . width: = x[ 0 ] ;
lvstack. Column[ 1 ] . width: = x[ 1 ] ;
lvstack. Column[ 2 ] . width: = x[ 2 ] ;
end ;
2016-08-25 21:31:09 +02:00
end
else
begin
{$ifdef cpu32}
lvStack. Column[ 0 ] . Width: = lvStack. Canvas. TextWidth( 'DDDDDDDD' ) ;
lvStack. Column[ 1 ] . Width: = lvStack. Canvas. TextWidth( 'DDDDDDDD' ) ;
{$else}
2021-01-24 22:37:53 +01:00
lvStack. Column[ 0 ] . Width: = lvStack. Canvas. TextWidth( 'DDDDDDDDDDDDDD' ) ;
lvStack. Column[ 1 ] . Width: = lvStack. Canvas. TextWidth( 'DDDDDDDDDDDDDD' ) ;
2016-08-25 21:31:09 +02:00
2021-01-24 22:37:53 +01:00
w: = lvStack. Column[ 0 ] . Width+ lvStack. Column[ 1 ] . Width;
if ( lvStack. ColumnCount> 2 ) and ( lvStack. Column[ 2 ] . Visible) then
begin
lvStack. Column[ 2 ] . Width: = lvStack. Canvas. TextWidth( 'DDDDDDDDDDDDDD' ) ;
w: = w+ lvStack. Column[ 2 ] . Width;
end ;
2016-08-25 21:31:09 +02:00
2021-01-24 22:37:53 +01:00
clientwidth: = w;
{$endif}
2016-08-25 21:31:09 +02:00
2011-07-04 19:52:53 +00:00
end ;
end ;
2013-11-12 23:44:04 +00:00
procedure TfrmStackView. lvStackCustomDrawItem( Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean ) ;
var
address: ptruint;
c: tcolor;
2011-07-04 19:52:53 +00:00
begin
2013-11-12 23:44:04 +00:00
address: = ptruint( item. data) ;
if colors. GetData( address, c) then
sender. canvas. brush. color: = c;
DefaultDraw: = true ;
end ;
2011-07-04 19:52:53 +00:00
2013-11-12 23:44:04 +00:00
procedure TfrmStackView. FormCreate( Sender: TObject) ;
begin
2013-11-13 00:09:59 +00:00
ColorDialog1. color: = clWhite;
2013-11-12 23:44:04 +00:00
colors: = TMap. create( ituPtrSize, sizeof( TColor) ) ;
2011-07-04 19:52:53 +00:00
end ;
procedure TfrmStackView. FormClose( Sender: TObject; var CloseAction: TCloseAction) ;
2018-06-11 15:36:17 +02:00
var x: array of integer ;
2011-07-04 19:52:53 +00:00
begin
2018-06-11 15:36:17 +02:00
setlength( x, 3 ) ;
x[ 0 ] : = lvstack. Column[ 0 ] . Width;
x[ 1 ] : = lvstack. Column[ 1 ] . Width;
x[ 2 ] : = lvstack. Column[ 2 ] . Width;
SaveFormPosition( self, x) ;
2011-07-04 19:52:53 +00:00
end ;
2013-11-12 22:42:47 +00:00
procedure TfrmStackView. FindDialog1Find( Sender: TObject) ;
var
i: integer ;
s: string ;
begin
miFindNext. enabled: = true ;
s: = lowercase( finddialog1. FindText) ;
2013-11-12 23:44:04 +00:00
lvStack. MultiSelect: = false ;
2013-11-12 22:42:47 +00:00
for i: = lvStack. ItemIndex+ 1 to lvStack. Items. Count- 1 do
begin
if ( pos( s, lowercase( lvStack. Items[ i] . Caption) ) > 0 ) or
( pos( s, lowercase( lvStack. Items[ i] . SubItems[ 0 ] ) ) > 0 ) or
( pos( s, lowercase( lvStack. Items[ i] . SubItems[ 1 ] ) ) > 0 ) then
begin
2013-11-12 23:44:04 +00:00
2013-11-12 22:42:47 +00:00
lvStack. ItemIndex: = i;
2013-11-12 23:44:04 +00:00
lvStack. Items[ lvStack. ItemIndex] . Selected: = true ;
2013-11-12 22:42:47 +00:00
lvStack. Items[ lvStack. ItemIndex] . MakeVisible( false ) ;
2013-11-12 23:44:04 +00:00
lvStack. Selected: = lvStack. Items[ lvStack. ItemIndex] ;
lvStack. MultiSelect: = true ;
exit;
2013-11-12 22:42:47 +00:00
end ;
end ;
2013-11-12 23:44:04 +00:00
lvStack. MultiSelect: = true ;
beep;
2013-11-12 22:42:47 +00:00
end ;
2013-06-09 11:54:30 +00:00
procedure TfrmStackView. FormCloseQuery( Sender: TObject; var CanClose: boolean ) ;
var r: TModalResult;
i: integer ;
begin
canclose: = true ;
if allocs< > nil then
begin
2015-10-10 13:21:06 +02:00
r: = messagedlg( rsSVThisStackViewWindowHasAllocatedStackSnapshotsEtc, mtconfirmation, [ mbyes, mbno, mbCancel] , 0 ) ;
2013-06-09 11:54:30 +00:00
if not ( r in [ mryes, mrno] ) then
begin
canclose: = false ; //something else besides yes or no was clicked
exit;
end ;
if r= mryes then
begin
//free the allocated memory in the target process
for i: = 0 to allocs. count- 1 do
VirtualFreeEx( processhandle, allocs[ i] , 0 , MEM_RELEASE) ;
end ;
allocs. free;
allocs: = nil ;
end ;
end ;
2023-10-20 17:32:15 +02:00
procedure TfrmStackView. SetContextPointer( c: pointer ; stack: pbyte ; size: integer ) ;
2011-07-04 19:52:53 +00:00
var tempstringlist: tstringlist;
p1, p2: integer ;
i: integer ;
s: string ;
address: string ;
value: string ;
secondary: string ;
li: tlistitem;
2017-05-15 22:57:21 +02:00
refname: string ;
refaddress: ptruint;
2011-07-04 19:52:53 +00:00
begin
2023-10-20 17:32:15 +02:00
contexthandler: = getBestContextHandler;
2011-07-04 19:52:53 +00:00
self. c: = c;
self. stack: = stack;
self. size: = size;
tempstringlist: = tstringlist. create;
2013-06-09 11:54:30 +00:00
lvStack. BeginUpdate;
lvStack. Items. BeginUpdate;
2011-07-04 19:52:53 +00:00
try
2017-05-15 22:57:21 +02:00
if miAddESP. checked then
begin
2023-10-20 17:32:15 +02:00
refname: = contexthandler. StackPointerRegister^ . name ;
refaddress: = contexthandler. StackPointerRegister^ . getValue( c) ;
2017-05-15 22:57:21 +02:00
end
else
if miAddEBP. checked then
begin
2023-10-20 17:32:15 +02:00
refname: = contexthandler. FramePointerRegister^ . name ;
refaddress: = contexthandler. FramePointerRegister^ . getValue( c) ;
2017-05-15 22:57:21 +02:00
end
else
if miAddRef. checked then
begin
refname: = ' ' ;
refaddress: = StackReference;
end ;
2023-10-20 17:32:15 +02:00
ce_stacktrace( contexthandler. StackPointerRegister^ . getValue( c) , contexthandler. FramePointerRegister^ . getValue( c) , contexthandler. InstructionPointerRegister^ . getValue( c) , pbytearray( stack) , size, tempstringlist, true , false , false , 0 , refaddress, refname) ;
2011-07-04 19:52:53 +00:00
//now fill the listview with this information
lvStack. Items. Clear;
for i: = 0 to tempstringlist. count- 1 do
begin
s: = tempstringlist[ i] ;
p1: = posex( ' - ' , s) ;
p2: = posex( ' - ' , s, p1+ 1 ) ;
address: = copy( s, 1 , p1) ;
value: = copy( s, p1+ 3 , p2- p1- 3 ) ;
secondary: = copy( s, p2+ 3 , length( s) ) ;
li: = lvStack. Items. Add;
li. Caption: = address;
li. SubItems. Add( value) ;
li. subitems. add( secondary) ;
li. Data: = pointer( tempstringlist. objects[ i] ) ;
end ;
finally
tempstringlist. Free;
2013-06-09 11:54:30 +00:00
lvStack. items. EndUpdate;
lvStack. EndUpdate;
2011-07-04 19:52:53 +00:00
end ;
end ;
initialization
{$I frmStackViewUnit.lrs}
end .