📄 symbolhandler.pas
字号:
closest:=-1;
for i:=0 to modulelistpos-1 do
begin
if modulelist[i].baseaddress>currentaddress then
begin
closest:=i;
break;
end;
end;
//irst make sure there is a bigger module
for i:=0 to modulelistpos-1 do
if (modulelist[i].baseaddress>currentaddress) and (modulelist[i].baseaddress<modulelist[closest].baseaddress) then
closest:=i;
if modulelist[closest].baseaddress<currentaddress then exit; //nothing found
mi:=modulelist[closest];
inc(sizeleft,mi.baseaddress-currentaddress);
currentaddress:=mi.baseaddress;
end;
end;
finally
modulelistMREW.endread;
end;
end;
function TSymhandler.getmodulebyaddress(address: dword; var mi: TModuleInfo):BOOLEAN;
var i: integer;
begin
result:=false;
modulelistMREW.beginread;
for i:=0 to modulelistpos-1 do
if (address>=modulelist[i].baseaddress) and (address<modulelist[i].baseaddress+modulelist[i].basesize) then
begin
mi:=modulelist[i];
result:=true;
break;
end;
modulelistMREW.endread;
end;
function TSymhandler.getmodulebyname(modulename: string; var mi: TModuleInfo):BOOLEAN;
var i: integer;
begin
result:=false;
modulelistMREW.beginread;
for i:=0 to modulelistpos-1 do
if (uppercase(modulelist[i].modulename)=uppercase(modulename)) then
begin
mi:=modulelist[i];
result:=true;
break;
end;
modulelistMREW.endread;
end;
function TSymhandler.getNameFromAddress(address:dword;symbols:boolean; modules: boolean):string;
var symbol :PImagehlpSymbol;
offset: dword;
s: string;
mi: tmoduleinfo;
begin
if symbols then
begin
//first see if it is a symbol
symbolloadervalid.beginread;
try
if (symbolloaderthread<>nil) then
begin
if isloaded then
begin
getmem(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
try
zeromemory(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
symbol.SizeOfStruct:=sizeof(IMAGEHLP_SYMBOL)+255;
symbol.MaxNameLength:=254;
if SymGetSymFromAddr(processhandle,address,@offset,symbol^) then
begin
//found it
s:=pchar(@symbol.Name[0]);
if offset=0 then
result:=s
else
result:=s+'+'+inttohex(offset,1);
exit;
end;
finally
freemem(symbol);
end;
end;
end;
finally
symbolloadervalid.endread;
end;
//check the userdefined symbols
result:=self.GetUserdefinedSymbolByAddress(address);
if result<>'' then exit;
end;
if modules then
begin
//get the dllname+offset
if getmodulebyaddress(address,mi) then
begin
if address-mi.baseaddress=0 then
result:=mi.modulename
else
result:=mi.modulename+'+'+inttohex(address-mi.baseaddress,1);
exit;
end;
end;
result:=inttohex(address,8); //default
end;
function TSymhandler.getNameFromAddress(address:dword):string;
begin
result:=getNameFromAddress(address,self.showsymbols,self.showmodules);
end;
function TSymhandler.getAddressFromName(name:string):dword;
begin
result:=getAddressFromName(name,true);
end;
function TSymhandler.getAddressFromName(name: string; waitforsymbols: boolean):dword;
var mi: tmoduleinfo;
newaddress: string;
symbol :PImagehlpSymbol;
oldoptions: dword;
offset: dword;
sn: string;
i: integer;
ws: widestring;
pws: pwidechar;
begin
result:=0;
val('$'+name,result,i);
if i=0 then exit; //it's a valid hexadecimal string
try
//first cut of the name from the offset
offset:=0;
for i:=length(name)-1 downto 1 do
if name[i] in ['+','-'] then
begin
sn:=copy(name,i+1,length(name));
offset:=strtoint('$'+sn);
if name[i]='-' then
offset:=-offset;
name:=copy(name,1,i-1);
break;
end;
except
raise exception.create(sn+' is not a valid value');
end;
val('$'+name,result,i);
if i=0 then
begin
result:=result+offset;
exit; //it was a simple +/- calculation
end;
//see if it is a module
if getmodulebyname(name,mi) then
result:=mi.baseaddress+offset
else
begin
//if not, see if you can find it as a symbol
//first check the userdefined symbols (small list, so faster than the symbols)
result:=GetUserdefinedSymbolByName(name);
if result<>0 then
begin
result:=result+offset;
exit;
end;
{$ifndef autoassemblerdll}
{if (darkbytekernel<>0) and (length(name)>3) then
begin
ws:=name;
pws:=@ws[1];
result:=dword(GetKProcAddress(pws));
if result<>0 then
begin
result:=result+offset;
exit;
end;
end; }
{$endif}
symbolloadervalid.beginread;
try
if (symbolloaderthread<>nil) then
begin
if symbolloaderthread.isloading and not waitforsymbols then
raise exception.create('This is not a valid address');
symbolloaderthread.WaitFor; //wait for it to finish if it's still busy
//it's not a valid address, it's not a calculation, it's not a modulename+offset, so lets see if it's a module
getmem(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
try
zeromemory(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
symbol.SizeOfStruct:=sizeof(IMAGEHLP_SYMBOL)+255;
symbol.MaxNameLength:=254;
if SymGetSymFromName(processhandle,pchar(name),symbol^) then
result:=symbol.Address+offset
else
raise exception.Create('This is not a valid address'); //no hex string, no module, no symbol, so invalid
finally
freemem(symbol);
end;
end else
raise exception.Create('This is not a valid address');
finally
symbolloadervalid.endread;
end;
end
end;
procedure TSymhandler.loadmodulelist;
var
ths: thandle;
me32:MODULEENTRY32;
x: pchar;
begin
modulelistMREW.BeginWrite;
try
modulelistpos:=0;
if processid=0 then exit;
//refresh the module list
ths:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processid);
if ths<>0 then
begin
me32.dwSize:=sizeof(MODULEENTRY32);
if ths<>0 then
begin
try
if module32first(ths,me32) then
repeat
if modulelistpos+1>=length(modulelist) then
setlength(modulelist,length(modulelist)*2);
x:=me32.szExePath;
modulelist[modulelistpos].modulename:=extractfilename(x);
modulelist[modulelistpos].baseaddress:=dword(me32.modBaseAddr);
modulelist[modulelistpos].basesize:=me32.modBaseSize;
inc(modulelistpos);
until not module32next(ths,me32);
finally
closehandle(ths);
end;
end;
end;
finally
modulelistmrew.EndWrite;
end;
end;
destructor TSymhandler.destroy;
begin
if symbolloaderthread<>nil then
begin
symbolloaderthread.Terminate;
symbolloaderthread.WaitFor;
symbolloaderthread.free;
end;
symbolloadervalid.Free;
modulelistMREW.free;
userdefinedsymbolsMREW.free;
setlength(userdefinedsymbols,0);
setlength(modulelist,0);
end;
constructor TSymhandler.create;
begin
symbolloadervalid:=TMultiReadExclusiveWriteSynchronizer.create;
modulelistMREW:=TMultiReadExclusiveWriteSynchronizer.create;
userdefinedsymbolsMREW:=TMultireadExclusiveWriteSynchronizer.create;
setlength(userdefinedsymbols,32);
setlength(modulelist,32);
showmodules:=false;
showsymbols:=true;
end;
initialization
symbolprocesshandle:=0;
symhandler:=tsymhandler.create;
finalization
symhandler.free;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -