Skip to content

Commit

Permalink
druntime: Update GNU implementation of callWithStackShell
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuclaw committed Jan 19, 2025
1 parent 6acbae5 commit 07a002b
Showing 1 changed file with 101 additions and 2 deletions.
103 changes: 101 additions & 2 deletions druntime/src/core/thread/osthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -1295,8 +1295,107 @@ in (fn)
void *sp = void;
version (GNU)
{
__builtin_unwind_init();
sp = &sp;
// The generic solution below using a call to __builtin_unwind_init ()
// followed by an assignment to sp has two issues:
// 1) On some archs it stores a huge amount of FP and Vector state which
// is not the subject of the scan - and, indeed might produce false
// hits.
// 2) Even on archs like X86, where there are no callee-saved FPRs/VRs there
// tend to be 'holes' in the frame allocations (to deal with alignment) which
// also will contain random data which could produce false positives.
// This solution stores only the integer callee-saved registers.
version (X86)
{
void*[3] regs = void;
asm pure nothrow @nogc
{
"movl %%ebx, %0" : "=m" (regs[0]);
"movl %%esi, %0" : "=m" (regs[1]);
"movl %%edi, %0" : "=m" (regs[2]);
}
sp = cast(void*)&regs[0];
}
else version (X86_64)
{
void*[5] regs = void;
asm pure nothrow @nogc
{
"movq %%rbx, %0" : "=m" (regs[0]);
"movq %%r12, %0" : "=m" (regs[1]);
"movq %%r13, %0" : "=m" (regs[2]);
"movq %%r14, %0" : "=m" (regs[3]);
"movq %%r15, %0" : "=m" (regs[4]);
}
sp = cast(void*)&regs[0];
}
else version (PPC)
{
void*[19] regs = void;
version (Darwin)
enum regname = "r";
else
enum regname = "";
static foreach (i; 0 .. regs.length)
{{
enum int j = 13 + i; // source register
asm pure nothrow @nogc
{
"stw "~regname~j.stringof~", %0" : "=m" (regs[i]);
}
}}
sp = cast(void*)&regs[0];
}
else version (PPC64)
{
void*[19] regs = void;
version (Darwin)
enum regname = "r";
else
enum regname = "";
static foreach (i; 0 .. regs.length)
{{
enum int j = 13 + i; // source register
asm pure nothrow @nogc
{
"std "~regname~j.stringof~", %0" : "=m" (regs[i]);
}
}}
sp = cast(void*)&regs[0];
}
else version (AArch64)
{
// Callee-save registers, x19-x28 according to AAPCS64, section
// 5.1.1. Include x29 fp because it optionally can be a callee
// saved reg
size_t[11] regs = void;
// store the registers in pairs
asm pure nothrow @nogc
{
"stp x19, x20, %0" : "=m" (regs[ 0]), "=m" (regs[1]);
"stp x21, x22, %0" : "=m" (regs[ 2]), "=m" (regs[3]);
"stp x23, x24, %0" : "=m" (regs[ 4]), "=m" (regs[5]);
"stp x25, x26, %0" : "=m" (regs[ 6]), "=m" (regs[7]);
"stp x27, x28, %0" : "=m" (regs[ 8]), "=m" (regs[9]);
"str x29, %0" : "=m" (regs[10]);
"mov %0, sp" : "=r" (sp);
}
}
else version (ARM)
{
// Callee-save registers, according to AAPCS, section 5.1.1.
// arm and thumb2 instructions
size_t[8] regs = void;
asm pure nothrow @nogc
{
"stm %0, {r4-r11}" : : "r" (regs.ptr) : "memory";
"mov %0, sp" : "=r" (sp);
}
}
else
{
__builtin_unwind_init();
sp = &sp;
}
}
else version (AsmX86_Posix)
{
Expand Down

0 comments on commit 07a002b

Please sign in to comment.