* Xtensa: patch by Christo Crause: add support for windowed ABI stack dump, resolves #37583

git-svn-id: trunk@46463 -
This commit is contained in:
florian 2020-08-16 21:05:15 +00:00
parent 324deca817
commit 66e682dfdd
3 changed files with 109 additions and 10 deletions

View File

@ -169,7 +169,7 @@ finalization
Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
{ to get a nice symify }
Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
dump_stack(pstdout^,ErrorBase);
dump_stack(pstdout^,ErrorBase,erroraddr);
Writeln(pstdout^,'');
End;
SysFlushStdIO;

View File

@ -208,6 +208,7 @@ const calculated_cmdline:Pchar=nil;
{*****************************************************************************
Misc. System Dependent Functions
*****************************************************************************}
{$ifndef FPC_SYSTEM_HAS_STACKTOP}
var
_stack_top: record end; external name '_stack_top';
@ -215,6 +216,7 @@ function StackTop: pointer;
begin
StackTop:=@_stack_top;
end;
{$endif FPC_SYSTEM_HAS_STACKTOP}
procedure haltproc;cdecl;external name '_haltproc';

View File

@ -31,27 +31,114 @@ begin
SysInitFPU;
end;
{$ifdef fpc_abi_windowed}
const
// Minimum call8 calls to force register spilling to stack for caller of forceSpilledRegs
spillcount = 6;
procedure forceSpilledRegs(n: uint32); assembler; public name 'forcespilledregs';
label
done, fin;
asm
beqz a2, done
addi a10, a2, -1
call8 forcespilledregs
done:
bnez a2, fin
movi a15, 0
fin:
end;
procedure fixCodeAddress(var addr: pointer);
begin
// Check if valid code address
if ptruint(addr) and $C0000000 >= $40000000 then
begin
// Replace windowed call prefix
addr:=codepointer((ptruint(addr)and$00FFFFFF) or $40000000);
// Rewind to call instruction address
dec(addr,3);
end
else
addr:=nil;
end;
{$endif fpc_abi_windowed}
{$IFNDEF INTERNAL_BACKTRACE}
{$define FPC_SYSTEM_HAS_GET_FRAME}
function get_frame:pointer;assembler;nostackframe;
asm
end;
{$define FPC_SYSTEM_HAS_GET_FRAME}
function get_frame:pointer;assembler;
label
done;
asm
{$ifdef fpc_abi_windowed}
// Force registers to spill onto stack
movi a10, spillcount
call8 forcespilledregs
// now get frame pointer of caller
addi a2, a1, -12
l32i a2, a2, 0
done:
{$else}
mov a2, a1
{$endif}
end;
{$ENDIF not INTERNAL_BACKTRACE}
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
begin
{$ifdef fpc_abi_windowed}
forceSpilledRegs(spillcount);
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
begin
get_caller_addr:=pointer((framebp-16)^);
fixCodeAddress(get_caller_addr);
end
else
get_caller_addr:=nil;
{$else}
get_caller_addr:=nil;
{$endif}
end;
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
asm
function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
begin
{$ifdef fpc_abi_windowed}
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
begin
forceSpilledRegs(spillcount);
get_caller_frame:=pointer((framebp-12)^);
end
else
get_caller_frame:=nil;
{$else}
get_caller_frame:=nil;
{$endif}
end;
{$ifdef fpc_abi_windowed}
{$define FPC_SYSTEM_HAS_GET_CALLER_STACKINFO}
procedure get_caller_stackinfo(var framebp : pointer; var addr : codepointer);
begin
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
begin
forceSpilledRegs(spillcount);
addr:=codepointer((framebp-16)^);
framebp := pointer((framebp-12)^);
fixCodeAddress(addr);
end
else
begin
addr:=nil;
framebp:=nil;
end;
end;
{$endif fpc_abi_windowed}
{$define FPC_SYSTEM_HAS_SPTR}
Function Sptr : pointer;assembler;
asm
@ -59,6 +146,16 @@ Function Sptr : pointer;assembler;
end;
{$define FPC_SYSTEM_HAS_STACKTOP}
// Interim fix for now, set to large address
// TODO: provide more realistic value, possibly by inspecting stack pointer
// when main or task is started
function StackTop: pointer;
begin
StackTop:=pointer($3fffffff);
end;
function InterLockedDecrement (var Target: longint) : longint;
var
temp_sreg : byte;