8
#include <stdint.h>
uint64_t rip;
int main()
{
    asm(
        "movq %%rip, %0\n" : "=m" (rip)
        );

    sleep(10);
}

When I compile I get

cc -m64    rip.c   -o rip
/tmp/ccwNbZi1.s: Assembler messages:
/tmp/ccwNbZi1.s:12: Error: suffix or operands invalid for `movq'
make: *** [rip] Error 1
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
dbbd
  • 864
  • 1
  • 8
  • 23
  • 3
    You need to hack around it: [Get address of current instruction for x86](http://stackoverflow.com/questions/7932287/get-address-of-current-instruction-for-x86) – Mysticial Sep 12 '12 at 23:34

2 Answers2

21

You can't read (E|R)IP because there's no x86(/64) instruction to read it directly.

The only way to "read" it is to make a call with the CALL instruction. It will save the return address on the stack and that one you can read.

UPDATE: In 64-bit mode you can exploit the RIP-relative addressing, so LEA RAX, [RIP] will give you the address of itself in RAX. Yet another workaround is MOV RAX, $ in assembly.

Benjamin Hodgson
  • 42,952
  • 15
  • 108
  • 157
Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • 9
    The `mov rax, $` would either be hardcoded by the linker, removing position-independence, or require a relocation at runtime. I would strongly suggest using `lea rax, [rip]` instead. – ughoavgfhw Sep 13 '12 at 01:32
  • 1
    @ughoavgfhw There was nothing in the question regarding position-(in)dependence. – Alexey Frunze Sep 13 '12 at 01:33
  • 3
    That's why I was only strongly *suggesting* it. Also, position independence is a very common goal in modern programs, mostly for security reasons (ASLR). At least Apple's compilers/assemblers require it for 64-bit programs. – ughoavgfhw Sep 13 '12 at 01:37
  • 1
    I don't think `mov rax, $` would make the executable not relocatable for ASLR or any other purposes. The linker and loader should be able to handle it. – Alexey Frunze Sep 13 '12 at 02:42
  • 3
    @AlexeyFrunze Sure, `mov rax,$` is still relocatable, but it's no longer position independent. Just consider an assembly routine, which moves a code block a few bytes: After the move `lea rax,[rip]` will still work, but `mov rax,$` no longer will. – Gunther Piez Sep 13 '12 at 08:24
  • 1
    @drhirsch That will only be a problem if you try to copy/move the already compiled/relocated code manually inside the executing program. – Alexey Frunze Sep 13 '12 at 11:22
  • 3
    Yes, thats exactly what I meant. Assembly is often used for exactly that kind of things. And it is rather "loading a constant which happen to be a pointer to the current address of execution after relocation" than "loading rip". – Gunther Piez Sep 13 '12 at 11:51
-1

The only way I can think of to get/set %rip under x86_64 is to use ptrace(). Below is copied from source of ltrace.

void* addr = ptrace(PTRACE_PEEKUSER, pid, (8 * RIP), 0);
ptrace(PTRACE_POKEUSER, pid, (8 * RIP), addr);

where RIP is a macro defined in /usr/include/sys/reg.h

andoryu-
  • 116
  • 4
  • RIP-relative `lea` to read it, `jmp` to write it. This question is about the current thread's RIP, not some other process. – Peter Cordes Feb 22 '18 at 17:53