[llvmlinux] Global vs. Local named registers

Renato Golin renato.golin at linaro.org
Wed May 21 11:47:43 UTC 2014


On 21 May 2014 12:36, PaX Team <pageexec at gmail.com> wrote:
> perhaps i'm asking the obvious, but where does linux have such a
> construct? it sounds pretty crazy to attempt to modify the stack
> pointer and similar registers this way...

Heh, we all asked that question one day... :)

The point here is when writing very low-level code (like unwinding)
while still wanting to interoperate with C code. Interoperating
between asm and C can be complex, especially when structure layout,
type sizes and others can change, so if your code only access certain
registers, like the stack pointer, it'd be a lot easier to maintain if
the underlying code was written in C and the stack was accessed via a
special construct.

For instance:

register unsigned long current_sp asm ("sp");

void *return_address(unsigned int level)
{
  struct return_address_data data;
  struct stackframe frame;

  data.level = level + 2;
  data.addr = NULL;

  frame.fp = (unsigned long)__builtin_frame_address(0);
  frame.sp = current_sp;
  frame.lr = (unsigned long)__builtin_return_address(0);
  frame.pc = (unsigned long)return_address;

  walk_stackframe(&frame, save_return_addr, &data);

  if (!data.level)
    return data.addr;
  else
    return NULL;
}

This is accessing both the stack pointer and the frame pointer (in
some hardware specific way), which is a lot more readable than if it
was written in ASM. Also, if the structure stackframe changes, it'll
be a compiler error (not an execution error) if this function is not
changed accordingly. So, in some special cases, having access to some
registers is actually better than the alternative.

cheers,
--renato


More information about the LLVMLinux mailing list