~skeeto/public-inbox

1

Re: Practical libc-free threading on Linux

Gaelan Steele <gbs@canishe.com>
Details
Message ID
<8999CB90-F5B5-4ECE-ADD1-E05F3F85745D@canishe.com>
DKIM signature
pass
Download raw message
> I wish doing really basic things without libc on Linux didn’t require so much
> assembly.

GCC/Clang provide the builtin __builtin_frame_address(), which I’ve used in the
past to get argc/argv in pure C. I’m not entirely sure if it’s guaranteed to work,
but it worked for me across GCC and Clang, with or without optimizations.

Here’s the (old, untested for a couple years) code:

__attribute__ ((force_align_arg_pointer))
_Noreturn void _start() {
  // find arguments: per the SysV ABI, these are placed on the stack when
  // _start is invoked. Conveniently, gcc/clang give us __builtin_frame_address,
  // which gives us a stable way to access the memory above our stack frame
  // without worrying about things like the size of our stack frame or
  // whether the compiler might optimize out rbp.
  
  // This +1 offset is inexplicable: my reading of the ABI is that argc should
  // be exactly at %rsp when the entry point is called, but actually there are
  // 8 zero bytes first. Either I'm misunderstanding something (likely), or the
  // ABI doesn't match what Linux actually does.
  long* argc_ptr = ((long*) __builtin_frame_address(0)) + 1;
  long argc = *argc_ptr;
  char** argv = (char**) (argc_ptr + 1);

Re: Practical libc-free threading on Linux

Details
Message ID
<20230324030214.o6zjjqr4bupqugul@nullprogram.com>
In-Reply-To
<8999CB90-F5B5-4ECE-ADD1-E05F3F85745D@canishe.com> (view parent)
DKIM signature
missing
Download raw message
Interesting, thanks! I had tried something like this myself, but couldn't 
get it working reliably. However, your example works in every case I've 
tried on x86-64. Maybe I was using the wrong built-in before. I was also 
able to grab the environment pointer:

    char **envp = (char **)(argc_ptr + 1 + argc + 1);

Perhaps this will be useful! It also works on ARM64 at -O1 and higher, but 
not at -O0 or -Og. Unfortunate since ultimately it would be nice to have a 
pure C entry point rather than special _start assembly for most targets. 
Here's my test program:

https://gist.github.com/skeeto/e7ff8823d8801a5b483c109fc84b6ab5
Reply to thread Export thread (mbox)