x86 PROCEDURES (FUNCTIONS) CONTROL FLOW Recall: Two ways to - - PowerPoint PPT Presentation

x86 procedures functions control flow
SMART_READER_LITE
LIVE PREVIEW

x86 PROCEDURES (FUNCTIONS) CONTROL FLOW Recall: Two ways to - - PowerPoint PPT Presentation

x86 PROCEDURES (FUNCTIONS) CONTROL FLOW Recall: Two ways to change program control flow Jump instructions Call instructions Function A unit of code we can call Similar to a jump, except it can return Must


slide-1
SLIDE 1

x86 PROCEDURES (FUNCTIONS)

slide-2
SLIDE 2

Recall: Two ways to change program control flow ▸ “Jump” instructions ▸ “Call” instructions Function ▸ A unit of code we can call ▸ Similar to a jump, except it can return ▸ Must support passing data as function arguments and return values Also referred to as a procedure, method, or subroutine But before we continue, we first have to understand how a stack works…

CONTROL FLOW

2

slide-3
SLIDE 3

Region of memory managed with last-in, first-out discipline ▸ Grows toward lower addresses ▸ %rsp Register indicates top element of stack ▹ “Top” element has lowest address The stack is essential for function calls!

x86-64 STACK

3

slide-4
SLIDE 4

Pushing ▸ pushq Src ▹ Fetch operand at Src ▹ Decrement %rsp by 8 ▹ Write operand at address given by %rsp ▸ e.g. pushq %rax ▹ subq $8, %rsp ▹ movq %rax,(%rsp)

PUSHING TO A STACK

4

slide-5
SLIDE 5

Popping ▸ popq Dest ▹ Read operand at address given by %rsp ▹ Write to Dest ▹ Increment %rsp by 8 ▸ e.g. popq %rax ▹ movq (%rsp),%rax ▹ addq $8,%rsp

POPPING FROM A STACK

5

slide-6
SLIDE 6

STACK OPERATION EXAMPLES

6

slide-7
SLIDE 7

When foo calls who: ▸ foo is the caller, who is the callee ▸ Control is transferred to the ‘callee’ When function returns ▸ Control is transferred back to the ‘caller’ Last-called, first-return (LIFO) order naturally implemented via stack

CONTROL FLOW TERMINOLOGY

7

slide-8
SLIDE 8

The hardware provides machine instructions for this: Function call ▸ call label ▹ Push return address on stack (that is, the address of next instruction after the call) ▹ Jump to label Function return ▸ ret ▹ Pop return address from stack ▹ Jump to address

CONTROL FLOW INSTRUCTIONS

8

slide-9
SLIDE 9

CONTROL FLOW EXAMPLE

9

slide-10
SLIDE 10

CONTROL FLOW EXAMPLE

10

slide-11
SLIDE 11

CONTROL FLOW EXAMPLE

11

slide-12
SLIDE 12

CONTROL FLOW EXAMPLE

12

slide-13
SLIDE 13

What does this code do? call next next: popq %rax What is the value of %rax? What would this be useful for?

PRACTICE PROBLEM

13

The “call” will cause the address of the “popq” instruction to be pushed onto the stack. Then, the popq instruction will pop that address (its own address) off, and store it into rax. Malware writers like to do this, because it lets them figure out where in the (virtual memory space) they are.

slide-14
SLIDE 14

For languages supporting recursion (C, Java), code must be re-entrant ▸ Multiple simultaneous instantiations of a single function ▸ Must store multiple versions of arguments, local variables, return address ▹ Return address ▹ Local variables ▹ Function arguments (if necessary) ▹ Saved register state (if necessary) Implemented with stack frames ▸ Upon function invocation ▹ Stack frame created ▹ Stack frame pushed onto stack ▸ Upon function completion ▹ Stack frame popped off stack ▹ Caller’s frame recovered

FUNCTION CALLS AND STACK FRAMES

14

slide-15
SLIDE 15

CALL CHAIN EXAMPLE

15

slide-16
SLIDE 16

CALL CHAIN EXAMPLE

16

slide-17
SLIDE 17

CALL CHAIN EXAMPLE

17

slide-18
SLIDE 18

CALL CHAIN EXAMPLE

18

slide-19
SLIDE 19

CALL CHAIN EXAMPLE

19

slide-20
SLIDE 20

CALL CHAIN EXAMPLE

20

slide-21
SLIDE 21

CALL CHAIN EXAMPLE

21

slide-22
SLIDE 22

CALL CHAIN EXAMPLE

22

slide-23
SLIDE 23

CALL CHAIN EXAMPLE

23

slide-24
SLIDE 24

CALL CHAIN EXAMPLE

24

slide-25
SLIDE 25

CALL CHAIN EXAMPLE

25

slide-26
SLIDE 26

CALL CHAIN EXAMPLE

26

slide-27
SLIDE 27

CALL CHAIN EXAMPLE

27

slide-28
SLIDE 28

Caller Stack Frame (Pink) ▸ Function arguments for callee ▹ Only used with 7+ integer arguments ▹ Arguments 1-6 passed in registers ▸ Return address ▹ Pushed by call instruction Callee Stack Frame (Yellow) (From Top to Bottom) ▸ Old frame pointer (optional) ▸ Local variables (optional) ▹ If can’t keep in registers ▸ Saved register context (optional) ▹ If certain registers needed ▸ Function arguments for next call

X86-64 / LINUX STACK FRAME

28

slide-29
SLIDE 29

Compiler can decide to simplify implementation ▸ Can omit local variables and saved registers for simple functions with few variables ▸ Can avoid using pushq and popq to manage frame ▸ Can even avoid using the call instruction!

X86-64 / LINUX STACK FRAME

29

slide-30
SLIDE 30

Initially Passed via Registers

FUNCTION ARGUMENTS

30

Overflow onto stack when needed

%rdi %rsi %rdx %rcx %r8 %r9 Argument n . . . Argument 8 Argument 7

“Diane’s Silk Dress Cost 89 Dollars” Return values given back on

%rax

slide-31
SLIDE 31

SWAP REVISITED

31

Function arguments all passed in registers ▸ First argument (xp) in %rdi, second argument (yp) in %rsi ▸ 64-bit pointers No stack operations required (except ret) ▸ Can hold all function arguments and local variables in registers ▸ Does not call another function so frame allocation not necessary

void swap(long *xp, long *yp) { long t0 = *xp; long t1 = *yp; *xp = t1; *yp = t0; } swap: movq (%rdi), %rdx movq (%rsi), %rax movq %rax, (%rdi) movq %rdx, (%rsi) ret

slide-32
SLIDE 32

FUNCTION ARGUMENTS BEYOND 6

32

Given the C function above, identify function arguments being passed to foo:

call_foo() { long a[16]; foo(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]); }

0000000000000000 <call_foo>: 0: sub $0xA8,%rsp 7: mov 0x68(%rsp),%rax c: mov %rax,0x18(%rsp) 11: mov 0x60(%rsp),%rax 16: mov %rax,0x10(%rsp) 1b: mov 0x58(%rsp),%rax 20: mov %rax,0x8(%rsp) 25: mov 0x50(%rsp),%rax 2a: mov %rax,(%rsp) 2e: mov 0x48(%rsp),%r9 33: mov 0x40(%rsp),%r8 38: mov 0x38(%rsp),%rcx 3d: mov 0x30(%rsp),%rdx 42: mov 0x28(%rsp),%rsi 47: mov 0x20(%rsp),%rdi 4c: callq <foo> 51: add $0xA8,%rsp 58: retq a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

slide-33
SLIDE 33

Held in registers if possible ▸ Allocate space on stack if too many (register spilling) ▸ Compiler allocates space on stack and updates %rsp How are they preserved if the current function calls another function? ▸ Compiler updates %rsp beyond local variables before issuing “call” What happens to them when the current function returns? ▸ Are lost (i.e. no longer valid)

LOCAL VARIABLES

33

slide-34
SLIDE 34

LOCAL VARIABLES

34

call_foo() { long a[16]; foo(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]); }

0000000000000000 <call_foo>: 0: sub $0xA8,%rsp 7: mov 0x68(%rsp),%rax c: mov %rax,0x18(%rsp) 11: mov 0x60(%rsp),%rax 16: mov %rax,0x10(%rsp) 1b: mov 0x58(%rsp),%rax 20: mov %rax,0x8(%rsp) 25: mov 0x50(%rsp),%rax 2a: mov %rax,(%rsp) 2e: mov 0x48(%rsp),%r9 33: mov 0x40(%rsp),%r8 38: mov 0x38(%rsp),%rcx 3d: mov 0x30(%rsp),%rdx 42: mov 0x28(%rsp),%rsi 47: mov 0x20(%rsp),%rdi 4c: callq <foo> 51: add $0xA8,%rsp 58: retq Makes room for both a[16] and partial argument build for foo. Puts the stack pointer back to where it was at address 0x0.

slide-35
SLIDE 35

Consider the following code:

int* func(int x) { int n; int *np; n = x; np = &n; return np; }

What does np point to after function returns? What happens if np is dereferenced? Local variables are “lost” when function returns ▸ Address referred to is no longer part of the stack ▸ Can be overwritten by other function calls ▸ Dereference will return whatever is at location (can be arbitrary)

SCOPING ISSUES WITH LOCAL VARIABLES

35

slide-36
SLIDE 36

PUTTING IT ALL TOGETHER: INCR()

36

slide-37
SLIDE 37

PUTTING IT ALL TOGETHER: INCR()

37

slide-38
SLIDE 38

PUTTING IT ALL TOGETHER: INCR()

38

slide-39
SLIDE 39

PUTTING IT ALL TOGETHER: INCR()

39

slide-40
SLIDE 40

PUTTING IT ALL TOGETHER: INCR()

40

slide-41
SLIDE 41

PUTTING IT ALL TOGETHER: INCR()

41

slide-42
SLIDE 42

When function1() calls function2(): ▸ function1 is the “caller” ▸ function2 is the “callee” Can Register be Used for Temporary Storage? ▸ Need some coordination between caller and callee on register usage Conventions ▸ “Caller Save” ▹ Caller saves temporary in its frame before calling ▸ “Callee Save” ▹ Callee saves temporary in its frame before using ▹ Callee restores values before returning

REGISTER SAVING CONVENTIONS

42

slide-43
SLIDE 43

Can be modified by function being called ▸ %rax ▹ Return value ▸ %rdi, %rsi, %rdx, %rcx, %r8, %r9 ▹ Function arguments ▸ %r10, %r11 ▹ Temporaries The caller is responsible for saving these before a call!

X86-64 CALLER SAVED REGISTERS

43

slide-44
SLIDE 44

Function being called must save and restore ▸ %rbx, %r12, %r13, %r14 ▸ %rbp ▹ May be used as frame pointer ▸ %rsp ▹ Special form of callee save ▹ Restored to original value upon return from function The callee (function being called) must save/resture these registers if they want to use them.

X86-64 CALLEE SAVED REGISTERS

44

slide-45
SLIDE 45

X86-64 INTEGER REGISTERS

45

slide-46
SLIDE 46

CALLEE SAVED EXAMPLE

46

slide-47
SLIDE 47

CALLEE SAVED EXAMPLE

47

slide-48
SLIDE 48

Recall integer arguments ▸ 64-bit registers used to pass ▸ %rdi, %rsi, %rdx, %rcx, %r8, %r9 Floating point ▸ Special vectored registers to pass (AVX-512) ▸ %zmm0 - %zmm31 ▹ Capacity for a vector of 8 doubles ▹ Also used for vectored integer operations (more later) ▹ Unique to x64 ▹ Special instruction sets: MMX -> SSE -> AVX -> AVX-512

X86-64 FLOATING POINT ARGUMENTS

48

slide-49
SLIDE 49

Linux IA32 cdecl ▸ Caller pushes arguments on stack before call ▸ Caller clears arguments off stack after call Win32 stdcall ▸ Caller pushes arguments on stack before call ▸ Callee clears arguments off stack before returning from call ▸ Saves some instructions since callee is already restoring the stack at the end of the function Fastcall ▸ Save memory operations by passing arguments in registers ▸ Microsoft implementation ▹ First two arguments passed in registers %ecx and %edx ▹ Code written on Windows must deal with stdcall and fastcall conventions ▸ Linux ▹ Must declare in function prototype which calling convention is being used ▹ http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

32-BIT CALLING CONVENTIONS

49

slide-50
SLIDE 50

thiscall ▸ Used for C++ ▸ Linux ▹ Same as cdecl, but first argument assumed to be “this” pointer ▸ Windows/Visual C++ ▹ “this” pointer passed in %ecx ▹ Callee cleans the stack when arguments are not variable length ▹ Caller cleans the stack when arguments are variable length

32-BIT CALLING CONVENTIONS

50