Sign in Join

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

Mailing lists / fpc-pascal / 2015-03

Help with Delphi ASM translation to FPC

3 messages · 1 person · –

Reply by email Subscribe to this list Your subscription

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

Graeme Geldenhuys

Hi,

Could somebody confirm if the Delphi ASM does the same as the FPC code? This code is used in a unit testing framework to help report the exact location of where an error was raised. It seems to work well in Delphi, but not in FPC.

Under FPC it seems to always return the same address, even though I might have had multiple test cases fail. I'm trying to eliminate where the possible issue could be.

==========================================
{$IFNDEF FPC}  // Delphi code
function IsBadPointer(const P: Pointer):boolean; register;
begin
  try
    Result := (P = nil) or
              ((Pointer(P^)  P) and (Pointer(P^) = P));
  except
    Result := true;
  end
end;

function CallerAddr: Pointer; assembler;
const

  CallerIP = $4;

asm
mov eax, ebp
call IsBadPointer
test eax,eax
jne @@Error

mov eax, [ebp].CallerIP
sub eax, 5 // 5 bytes for call

push eax
call IsBadPointer
test eax,eax
pop eax
je @@Finish

@@Error:
xor eax, eax
@@Finish:
end;

{$ELSE}
// FPC cross-platform implementation
function CallerAddr: Pointer;
begin
  Result := get_caller_addr(get_frame);
end;
{$ENDIF}
==========================================

Here is sample code of its usage:

procedure TTestProc.Check(const condition: boolean; const ErrorMsg:
string);
begin
  OnCheckCalled;
  if (not condition) then
    Fail(ErrorMsg, CallerAddr);
end;

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
Graeme Geldenhuys wrote 5 lines
// FPC cross-platform implementation function CallerAddr: Pointer; begin Result := get_caller_addr(get_frame); end;

I was told from another source my FPC implementation was incorrect and should rather be:

[Anybody that could explain the different to me? I would be very grateful.]

function CallerAddr: Pointer;
var
  bp: Pointer;
begin
  bp := get_caller_frame(get_frame);
  if bp  nil then
    Result := get_caller_addr(bp)
  else
    Result := nil;
end;

This now does cause different addresses for various unit test failures. Next part is to extract the line info information to confirm that the addresses I now see are indeed correct.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys
Graeme Geldenhuys wrote
Next part is to extract the line info information to confirm that the addresses I now see are indeed correct.

Success!!! :) Finally I have full details of where a failure occurs.

===========================================
tiOPFUnitTestsFPGui.Non persistent
tests.TTestTIUtils.tiInsertStringToStream: ETestFailure at $00000000006F1017 line 2835 of ../../UnitTests/Tests/tiUtils_TST.pas "Failed on 5"
Expected:
"EAssertionFailed"
But was:
"ETestFailure"
===========================================

I would still like to know if anybody could explain the difference between the two FPC implementations of CallerAddr() please.

Now on to the next part. For ETestErrors, I want to include a stack dump. This should be easy now.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email