Recent

Author Topic: Сall stack integrity  (Read 7580 times)

zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Сall stack integrity
« on: June 20, 2021, 02:30:50 pm »
Please explain to me where did the top of the stack go? Why is there no mention of the problem line from procedure doSomathing2;
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$ifdef fpc}{$mode ObjFPC}{$H+}{$endif}
  3. interface
  4. uses
  5.   SysUtils;
  6. procedure doSomathing1;
  7. implementation
  8. procedure doSomathing2;
  9. begin
  10.   writeln('doSomathing2.1');
  11.   pstring(0)^:='Bug emulation';
  12.   writeln('doSomathing2.2');
  13. end;
  14. procedure doSomathing1;
  15. begin
  16.   writeln('doSomathing1');
  17.   doSomathing2;
  18. end;
  19. begin
  20.   doSomathing1;
  21. end.
out:
Code: Pascal  [Select][+][-]
  1. D:\TEMP>project1.exe
  2. doSomathing1
  3. doSomathing2.1
  4. An unhandled exception occurred at $00405A96:
  5. EAccessViolation: Access violation
  6.   $00405A96  fpc_ansistr_assign,  line 179 of E:/ppsrc/rtl/inc/astrings.inc
  7.   $0040F882  DOSOMATHING1,  line 17 of unit1.pas
  8.   $0040F898  UNIT1_$$_init$,  line 20 of unit1.pas
  9.   $00408A54  fpc_initializeunits,  line 1101 of E:/ppsrc/rtl/inc/system.inc
how can I get this address?

In the debugger callstack is correct
Code: Pascal  [Select][+][-]
  1. D:\TEMP>gdb project1.exe
  2. GNU gdb (GDB) 7.2
  3. Copyright (C) 2010 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  7. and "show warranty" for details.
  8. This GDB was configured as "mingw32".
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>...
  11. Reading symbols from D:\TEMP/project1.exe...done.
  12. (gdb) run
  13. Starting program: D:\TEMP/project1.exe
  14. [New Thread 2624.0x2c54]
  15. [New Thread 2624.0x1898]
  16. [New Thread 2624.0x9e0]
  17. [New Thread 2624.0x2d34]
  18. doSomathing1
  19. doSomathing2.1
  20.  
  21. Program received signal SIGSEGV, Segmentation fault.
  22. fpc_ansistr_assign (DESTS=Cannot access memory at address 0x0
  23. ) at E:/ppsrc/rtl/inc/astrings.inc:180
  24. 180       if DestS=S2 then
  25. (gdb) bt
  26. #0  fpc_ansistr_assign (DESTS=Cannot access memory at address 0x0
  27. ) at E:/ppsrc/rtl/inc/astrings.inc:180
  28. #1  0x0040f81c in DOSOMATHING2 () at unit1.pas:11
  29. #2  0x0040f882 in DOSOMATHING1 () at unit1.pas:17
  30. #3  0x0040f898 in UNIT1_$$_init$ () at unit1.pas:20
  31. #4  0x00408a54 in fpc_initializeunits () at E:/ppsrc/rtl/inc/system.inc:1101
  32. #5  0x004016f9 in main () at D:/TEMP/project1.lpr:5
« Last Edit: June 20, 2021, 02:35:14 pm by zamtmn »

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 881
Re: Сall stack integrity
« Reply #1 on: June 20, 2021, 03:00:32 pm »
Have you compiled without optimisations? When optimisations are enabled, frame pointers can be removed which results in incomplete stack traces.

zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #2 on: June 20, 2021, 04:39:29 pm »
Yes, without optimization. I try O1 and O0

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7272
  • Debugger - SynEdit - and more
    • wiki
Re: Сall stack integrity
« Reply #3 on: June 20, 2021, 06:09:50 pm »
The problem is your fpc build is optimized.

And (my guess is) therefore  fpc_ansistr_assign does not have a "frame".

A frame means, that the register rbp or (ebp) is loaded with an address for that function, and that the function stores some info at that address (local vars, and how to get the caller)

A function that does not have it's own frame, has the info of the callers frame in rbp.

Thus the debugger sees:
- the instruction pointer is in fpc_ansistr_assign
- the frame in rbp points to DOSOMATHING1
  Because rbp belongs to DOSOMATHING2, and points to the parent of this.



As for gdb.

There are 2 possibilities.

- There may be debuginfo (for the rtl) that indicates fpc_ansistr_assign has no frame.
- Also gdb may analyse the frame found, and detect that DOSOMATHING2 did call DOSOMATHING1.

Whichever way gdb used to detect this, that is gdb advance.

The build in stack trace dumper ( -gl ) does not perform any of this.

For FpDebug this is on the todo list, but currently not done either.


zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #4 on: June 20, 2021, 08:08:51 pm »
>>The problem is your fpc build is optimized
no, no optimizations, but also no debug invormation


do I understand correctly that to see the last line of my program I need build fpc with debugging information?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7272
  • Debugger - SynEdit - and more
    • wiki
Re: Сall stack integrity
« Reply #5 on: June 20, 2021, 09:26:43 pm »
>>The problem is your fpc build is optimized
no, no optimizations, but also no debug invormation

do I understand correctly that to see the last line of my program I need build fpc with debugging information?
I don't think it makes a difference if you add debug info to your fpc/rtl build.

Somehow at least the address of fpc_ansistr_assign  is known already (as it shows up).
But that can be included from linker info. (If indeed your rtl has no debug info).

My judgement on the current outcome is made from the view of the debugger / frame dump code.
From my knowledges on how a stack is unrolled (i.e. parent frame being found), I can tell you that
- if any procedure in the stack does not have it's own frame
- then the caller/parent of that procedure is hidden.

Why the frame is omitted, I do not know. fpc_ansistr_assign  is a "compilerproc" maybe that is the reason.

-----------------
There is one more explanation (based on the same "frame info" issue.)

If the error happens very close to the entrance of a function (or to the end of it), then the function may not have had time to set up its frame.

------------------
I did a test your code here.
According to the debugger
- fpc_ansistr_assign  has a frame
- and fpc_ansistr_assign  has set up that frame when the error happens.


I run the resulting code from console => and I got a full trace
Code: [Select]
C:\Users\martin\AppData\Local\Temp>project1.exe
doSomathing1
doSomathing2.1
An unhandled exception occurred at $0000000100004E85:
EAccessViolation: Access violation
  $0000000100004E85  fpc_ansistr_assign,  line 180 of ../inc/astrings.inc
  $0000000100001756  doSomathing2,  line 9 of project1.lpr
  $00000001000017CD  doSomathing1,  line 15 of project1.lpr
  $00000001000017F3  $main,  line 18 of project1.lpr
  $0000000100001806  MAIN_WRAPPER,  line 67 of system.pp
  $000000010000FD00  EXE_ENTRY,  line 181 of system.pp
  $0000000100001704  _FPC_MAINCRTSTARTUP,  line 106 of sysinit.pp


- I did run my test with fpc 3.2.2
- Compiled 64 bits (that may make a difference sometimes)
- I used dwarf debug info (that may make a difference sometimes)
- My fpc has debug info, but I am not sure if that makes the difference.

For all else, you would have to check what changes, if any will make it work for you.




zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #6 on: June 20, 2021, 10:27:37 pm »
Martin_fr, thanks!
I use win32 trunk fpc. I got full trace only if build fpc with -0- option. This seems strange to me, I think that minimal optimizations should not interfere((

zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #7 on: June 21, 2021, 01:43:21 pm »
Martin_fr
>>For FpDebug this is on the todo list, but currently not done either.
When this is implemented, can it be used in a third-party application to build call stack on a crash?
Is there a bugtracker issue for I can track the status?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7272
  • Debugger - SynEdit - and more
    • wiki
Re: Сall stack integrity
« Reply #8 on: June 21, 2021, 03:00:16 pm »
Martin_fr
>>For FpDebug this is on the todo list, but currently not done either.
When this is implemented, can it be used in a third-party application to build call stack on a crash?
Is there a bugtracker issue for I can track the status?
There is no issue for it. It is on my personal todo list.

FpDebug is GPL, so any app under gpl can include that code.
However:
1) it may need some tweaks -> fpdebug by default reads from the "target process" which differs to the process in which it is running. That is it uses the Win-API or Kernel to access the memory of a debugged process, and that process must be paused.
However, I guess that can be tweaked.

2) It has no special entrypoints for that purpose. To use it, one has to understand a  part of the debugger.

3) It has a lot more code than -gl adds. So it will seriously add to the size of your exe.

4) It may give be that using fpdebug leads to more crashes and no output, even if -gl can handle it.

---
The code for -gl has been specially written, to minimize (or even fully avoid) memory allocation.

If your app crashes, there is a chance that memory is corrupted. That means that the memory manager itself will no longer be stable, as its internal data may also be corrupted.
If you allocate mem while dumping a stack, well that would be the next access violation....

FpDebug does allocate/deallocate mem. That can not be avoided.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7272
  • Debugger - SynEdit - and more
    • wiki
Re: Сall stack integrity
« Reply #9 on: June 21, 2021, 03:07:36 pm »
While it does not solve the skipped entries. The ide has a resolve feature (view > leaks and traces)

- If you build your code with dwarf debug info
- make a copy of the exe
- strip the copy, so it no longer has debug info
- ship the copy

your clients get a trace with address only (no line/unit info). (but still skipped frames :( )

You import that into leaks and traces, and "resolve" against the original file. (this must be the same build / the exact copy)

----
Test before use.

zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #10 on: June 21, 2021, 09:49:21 pm »
You suggest embedding the debugger in the application(( If there are no other solutions, we will have to use the compiler rebuilt with the -O- option.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 7272
  • Debugger - SynEdit - and more
    • wiki
Re: Сall stack integrity
« Reply #11 on: June 21, 2021, 10:36:05 pm »
You suggest embedding the debugger in the application(( If there are no other solutions, we will have to use the compiler rebuilt with the -O- option.
I don't suggest it.
I answered your question
When this is implemented, can it be used in a third-party application to build call stack on a crash?

It is not impossible to do it, but very very unpractical.


So yes -O-

I have no idea if -O1 is intended to make that diff.
Trunk has tons of changes to the optimizer

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 881
Re: Сall stack integrity
« Reply #12 on: June 21, 2021, 10:39:08 pm »
Note that the top level FPC Makefile by default adds -O2. If you specify -O1, then the result is "-O2 -O1" which means "enable level 2  optimizations and also enable level 1 optimizations" (which is the same as -O2, as -O2 includes -O1). If you only want -O1, use -O-1 (which means "disable all optimizations, then enable level 1 optimizations).

zamtmn

  • Sr. Member
  • ****
  • Posts: 396
Re: Сall stack integrity
« Reply #13 on: June 21, 2021, 10:53:43 pm »
Jonas Maebe
 :o Thanks!

 

TinyPortal © 2005-2018