Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble understanding an x86-64 function preamble

I am experiencing a crash, and while investigating I found myself totally blocked by the following code:

0000000000000a00 <_IO_vfprintf>:
a00:       55                      push   %rbp
a01:       48 89 e5                mov    %rsp,%rbp
a04:       41 57                   push   %r15
a06:       41 56                   push   %r14
a08:       41 55                   push   %r13
a0a:       41 54                   push   %r12
a0c:       53                      push   %rbx
a0d:       48 81 ec 48 06 00 00    sub    $0x648,%rsp
a14:       48 89 95 98 f9 ff ff    mov    %rdx,0xfffffffffffff998(%rbp)

This is generated by running objdump --disassemble /usr/lib64/libc.a on a 64-bit Linux x86 system, and then searching through the output. This is AT&T syntax, so destinations are on the right.

Specifically, I don't understand the last instruction. It seems to be writing the value of the rdx register into memory somewhere on the stack (far, far away), before the function has touched that register. To me, this doesn't make any sense.

I tried reading up on the calling conventions, and my best theory now is that rdx is used for a parameter, so the code is basically "returning" the parameter value directly. This is not the end of the function, so it's not really returning, of course.

like image 668
unwind Avatar asked Sep 23 '10 14:09

unwind


People also ask

How does x86 stack work?

All x86 architectures use a stack as a temporary storage area in RAM that allows the processor to quickly store and retrieve data in memory. The current top of the stack is pointed to by the esp register.

What is x64 assembly language?

x64 is a generic name for the 64-bit extensions to Intel‟s and AMD‟s 32-bit x86 instruction set architecture (ISA). AMD introduced the first version of x64, initially called x86-64 and later renamed AMD64. Intel named their implementation IA-32e and then EMT64.

What is the RDI register?

In Objective-C, the RDI register is the reference of the calling NSObject , RSI is the Selector, RDX is the first parameter and so on. In Swift, RDI is the first argument, RSI is the second parameter, and so on provided that the Swift method isn't using dynamic dispatch.


1 Answers

Yes, it's a parameter. The ABI used by Linux assigns up to 6 "INTEGER" (<= 64-bit integer, or pointer) type parameters to registers, in the obvious and easy-to-remember order %rdi, %rsi, %rdx, %rcx, %r8, %r9.

The stack frame is 1648 bytes (sub $0x648,%rsp claims 1608 bytes, plus 5 64-bit registers have been pushed before that), and 0xfffffffffffff998 is -1640.

So the code is storing the 3rd parameter near the bottom of the stack frame.

(Note: the Windows 64-bit ABI is different to the Linux one.)

like image 120
Matthew Slattery Avatar answered Sep 19 '22 01:09

Matthew Slattery