Jump to content

pudnivec

Members
  • Content Count

    13
  • Joined

  • Last visited

Community Reputation

1 Neutral
  1. Finally, I used your code from GitHub (https://github.com/Fr0sT-Brutal/Delphi_StackTraces), in which I took the liberty to make a few changes to account for dynamic address changes when using e.g. ASLR. Added MapAddrOffset: Pointer to variables var MapFileAvailable: Boolean; LineAddrs: TArray<TMapFileLineAddrInfo>; PublicAddrs: TArray<TMapFilePublicAddrInfo>; MapAddrOffset: Pointer; Added the output for MapAddrOffest: Pointer to the ReadMapFile procedure. procedure ReadMapFile(const MapFile: string; out LineAddrs: TArray<TMapFileLineAddrInfo>; out PublicAddrs: TArray<TMapFilePublicAddrInfo>; out MapAddrOffset: Pointer); var arr: TStrArray; CurrIdx, HighArr: Integer; UnitName: string; SegmentInfo: TMapFileSegmentStartAddrs; begin LineAddrs:= nil; PublicAddrs:= nil; arr:= Split(MapFile, NL); CurrIdx:= Low(arr); ReadSegments(arr, CurrIdx, SegmentInfo); ReadPublics(arr, CurrIdx, SegmentInfo, PublicAddrs); //Get MAP address offset MapAddrOffset:= SegmentInfo[1]; . . . . end; Added new function GetOrigMapProcAddress(AName: string): Pointer. function GetOrigMapProcAddress(AName: string): Pointer; var i: Integer; uRes: UInt64; begin Result:= Pointer(0); for i:= Low(PublicAddrs) to High(PublicAddrs) do begin if PublicAddrs[i].Name.Equals(AName) then begin uRes:= UInt64(PublicAddrs[i].Addr) - UInt64(MapAddrOffset); if uRes > High(NativeUInt) then uRes:= 0; Result:= Pointer(uRes); Break; end; end; end; Added new overloaded function GetAddrInfo(Addr, RealAddrOffset: Pointer; out AddrInfo: TMapFileAddrInfo): Boolean. function GetAddrInfo(Addr, RealAddrOffset: Pointer; out AddrInfo: TMapFileAddrInfo): Boolean; overload; var uRes: UInt64; begin uRes:= UInt64(Addr) - UInt64(RealAddrOffset) + UInt64(MapAddrOffset); if uRes > High(NativeUInt) then uRes:= 0; if not MapFileAvailable then Result:= False else Result:= GetAddrInfo(Pointer(uRes), LineAddrs, PublicAddrs, AddrInfo); end; Now it is enough to use this code in any application (including service app), which uses dynamic address change e.g. ASLR. To demonstrate the functionality I used the code from the service app: var RealAddressOffset: Pointer; function TMainService.GetRealAddressOffset: Pointer; var uRes: UInt64; begin uRes:= UInt64(MethodAddress('ServiceStart')) - UInt64(GetOrigMapProcAddress(UnitName + '.' + ClassName + '.ServiceStart')); if uRes > High(NativeUInt) then uRes:= 0; Result:= Pointer(uRes); end; function TMainService.GetAddressInfo(AAddress: Pointer): string; var tmpAddrInfo: TMapFileAddrInfo; begin GetAddrInfo(AAddr, RealAddressOffset, tmpAddrInfo); Result:= AddrInfoToString(tmpAddrInfo); end; Then just call this function e.g. as follows: GetAddressInfo(GetCurrentAddress);
  2. Interestingly, if I use your function function GetMethodName(AClass: TClass; Address: Pointer): string; which does not read data from the MAP file, with the same generated address pointer by MethodAddress, the correct method name is returned from the service app (but only for main class, not for private and public section). This indicates that most likely a bad MAP file is generated for the service app.
  3. I may have misspoken in my last post. The address of the method (procedure) does not change for the compiled service. It is still the same. What does change is the difference in subtraction for different procedures - see the following examples: 0001:003561A0 Unit1.TMainService.ServiceStart (MAP file address: 003561A0, service address (used with MethodAddress('ServiceStart') function): 004C71A0, 004C71A0 - 003561A0 = 171000 HEX (1.511,424 DEC) 0001:003576E0 Unit1.TMainService.ServiceStop (MAP file address: 003576C0, service address (used with MethodAddress('ServiceStop') function): 004C86E0, 004C86E0 - 003576C0 = 171020 HEX (1.511.456 DEC) * I used the MethodAddress function only for the purpose of this post, because it refers to the address of the beginning of the method (procedure). Interestingly, for procedure Unit1.TMainService.ServiceStart the difference between MAP file and service is 171000 HEX (1.511.424 DEC), but for procedure Unit1.TMainService.ServiceStop the difference is 171020 HEX (1.511.456 DEC). The difference in both cases should be 401000 HEX (4.198.400 DEC) as indicated in the service MAP file. Start Length Name Class 0001:00401000 0036EB7CH .text CODE 0002:00770000 0004E840H .data DATA 0003:007BF000 0000D4CCH .bss BSS 0004:00000000 00000280H .tls TLS 0005:00804000 00031710H .pdata PDATA For the classic application on the same machine the difference is 401000 HEX (4.198.400 DEC) for all mathods (procedures) as shown in the MAP file.
  4. ASLR is turned off. Booth app and service are on the same machine.
  5. The generated method address does not match (after or without 401000 HEX subtraction) adress of method in MAP file. Interestingly, the difference is different for each method (procedure). The MAP file service contains the same offset as the classic 401000 HEX application. Start Length Name Class 0001:00401000 0036EB7CH .text CODE 0002:00770000 0004E840H .data DATA 0003:007BF000 0000D4CCH .bss BSS 0004:00000000 00000280H .tls TLS 0005:00804000 00031710H .pdata PDATA Could it be that the MAP file is generated incorrectly? PS: The settings for both applications are exactly the same, including the compilation settings
  6. Can I ask you, why this solution does not work for windows service app?
  7. Thank you for the link. The code is inspiring, but for our needs I will use a slightly different solution.
  8. pudnivec

    Exception call stacks on Windows with only a few LOCs

    Thank you for the link. It's an inspiring post, but I'll use a slightly different solution for our needs.
  9. Perfect. You're the man for the job. Thank you again for all the information. It helped me a lot. I will now use the MAP file for detailed analysis of the application's behavior and errors.
  10. I found that the difference between the address in APP and MAP is still constant (even with other methods) 4.198.400 (DEC) or 401000 (HEX).. Do you know why?
  11. Thank you for your answers. The problem is that when I use the MAP file (detailed mode), different method addresses are listed: in APP the address is [007B6B90: frmMain->Button9Click] (own generated string with IntToHex(NativeInt(Address: Pointer - generated with ReturnAddress), 8)) and in MAP [003B5B90 frmMain.TFormMain.Button9Click] - 007B6B90 vs 003B5B90 :-(
  12. Hello, this method (GetMethodName) works only for main class. It does not display methods in the private and public section. Is there any solution to show methods in private and public section?
×