Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2003-09

heaptrc: web bug 2632

3 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Vincent Snijders

Hi,

Thanks to the open source character of fpc I could investigate bug 2632
(for details see: http://www.freepascal.org/bugs/showrec.php3?ID=2632 )
a bit further.
The crash occurs in this loop arround line 380 of heaptrc.pp.
  bp:=get_caller_frame(get_frame);
  for i:=1 to tracesize do
   begin
     pheap_mem_info(p)^.calls[i]:=get_caller_addr(bp);
     bp:=get_caller_frame(bp);
   end;

I ran this code in the debugger. The following table give the results of get_caller_frame and get_caller_addr.
0x2e0fca8 0x4175f7
0x2e0fcd0 0xbff72317
0x2e0fd10 0x4175e0
0x2e0fd58 0x75e00003
0x817a7 0x1eeb0028
0xb823eb00 access violation.

I have some idea what the code is supposed to do, but I am not sure. Please correct me if I am wrong.
I guess, that the get_caller_frame function tries to find the next frame pointer in the stack. But this assumes that there is always at every procedure entry bp is pushed. While this might be true for fpc programs, this isn't always the case. If there is function somewhere in the call stack, that didn't push the frame pointer, a wrong value is returned, which might lead to an access violation.
I think the values returned by get_caller_frame should be increasing, because they are allocated on the stack (at least in architectures where the stack grows downward). Therefore I added a check to test that the returned frame pointers should be greater than the original.

I added an extra local variable to hold the previous bp and the loop now
looks like this:
  bp:=get_caller_frame(get_frame);
  for i:=1 to tracesize do
   begin
     pheap_mem_info(p)^.calls[i]:=get_caller_addr(bp);
     oldbp := bp;
     bp:=get_caller_frame(bp);
     if (bp<oldbp) then
       bp:= 0;
   end;

I recompiled the rtl and run several test programs and the programs didn't crash anymore.
The check on the frame pointer could be more sophisticated if I knew a way to find out what the top of the stack is, so I could check if the frame pointer is in stack.

I hope this information is useful for fixing the bug. I want to thank the fpc developers for their effort creating such a wonderful compiler.

Regards,
Vincent Snijders.

Reply by email

Peter Vreman
Show quoted text 17 lines
I added an extra local variable to hold the previous bp and the loop now looks like this: bp:=get_caller_frame(get_frame); for i:=1 to tracesize do begin pheap_mem_info(p)^.calls[i]:=get_caller_addr(bp); oldbp := bp; bp:=get_caller_frame(bp); if (bp<oldbp) then bp:= 0; end; I recompiled the rtl and run several test programs and the programs didn't crash anymore. The check on the frame pointer could be more sophisticated if I knew a way to find out what the top of the stack is, so I could check if the frame pointer is in stack.

Thanks, i've applied the patch

Peter

Reply by email

Marco van de Voort
to Peter Vreman
Show quoted text 19 lines
>I added an extra local variable to hold the previous bp and the loop now >looks like this: > bp:=get_caller_frame(get_frame); > for i:=1 to tracesize do > begin > pheap_mem_info(p)^.calls[i]:=get_caller_addr(bp); > oldbp := bp; > bp:=get_caller_frame(bp); > if (bp<oldbp) then > bp:= 0; > end; > >I recompiled the rtl and run several test programs and the programs >didn't crash anymore. >The check on the frame pointer could be more sophisticated if I knew a >way to find out what the top of the stack is, so I could check if the >frame pointer is in stack. Thanks, i've applied the patch

Peter: We could save the initial stackptr in the initcode?

Reply by email