Printing Stack Frames

So, I'm currently studying stack frames, and I wanted to experiment with printing the stack frame (manually) of a function.

I have the following picture regarding the stack frame (I may be wrong):

|                                |  0xffff0fdc
+--------------------------------+
|              ...               |  0xffff0fd8
+--------------------------------+
|           parameter 2          |  0xffff0fd4
+--------------------------------+
|           parameter 1          |  0xffff0fd0
+--------------------------------+
|         return address         |  0xffff0fcc
+--------------------------------+
|        local variable 2        |  0xffff0fc8
+--------------------------------+
|        local variable 1        |  0xffff0fc4
+--------------------------------+

thus, I first wrote this function to achieve the above result and printed it:

void func(int a,int b)
{
    uint64_t loc = 0;
    uint64_t *sp = &loc;

    printf("%" PRIu64 "\n",*(sp));
    printf("%" PRIu64 "\n",*(sp+4));
    printf("%" PRIu64 "\n",*(sp+8));
    printf("%" PRIu64 "\n",*(sp+12));
}

int main()
{
    func(2,3);
    return 0;
}

and I get:

0

12884901890

51266344552759297

18034967110614932

definitely not what was expected

I also tried scanning through the stack to find one of the arguments:

while (*sp != a) sp++

without much success. What is wrong with my method?


I also had another question: Given a recursive function, just take factorial (int n), how can we determine the address where the base pointer is on the stack?


: , "func" . , .

                    pushq   %rbp
                    .cfi_def_cfa_offset 16
                    .cfi_offset 6, -16
                    movq    %rsp, %rbp
                    .cfi_def_cfa_register 6
                    subq    $32, %rsp
                    movl    %edi, -20(%rbp)
                    movl    %esi, -24(%rbp)

                   ***// uint64_t loc = 0;***

                    movq    $0, -16(%rbp)

                   ***// uint64_t *sp = &loc;***

                    leaq    -16(%rbp), %rax
                    movq    %rax, -8(%rbp)

                  ***// printf("%" PRIu64 "\n",*sp);***

                    movq    -8(%rbp), %rax
                    movq    (%rax), %rax
                    movq    %rax, %rsi
                    movl    $.LC0, %edi

                    movl    $0, %eax

                    call    printf

                    ***printf("%" PRIu64 "\n",*(sp+8));***

                    movq    -8(%rbp), %rax
                    addq    $64, %rax
                    movq    (%rax), %rax
                    movq    %rax, %rsi
                    movl    $.LC0, %edi

                    movl    $0, %eax

                    call    printf

                    ***// printf("%" PRIu64 "\n",*(sp+16));***

                    movq    -8(%rbp), %rax
                    subq    $-128, %rax
                    movq    (%rax), %rax
                    movq    %rax, %rsi
                    movl    $.LC0, %edi

                    movl    $0, %eax

                    call    printf

                   ***// printf("%" PRIu64 "\n",*(sp+32));***

                    movq    -8(%rbp), %rax
                    addq    $256, %rax

                    movq    (%rax), %rax
                    movq    %rax, %rsi
                    movl    $.LC0, %edi

                    movl    $0, %eax

                    call    printf

                    leave
                    .cfi_def_cfa 7, 8
                    ret

, , !

PS: -

+1
1

x86-64 ( ), . , .

, , :

        return address
rbp     saved rbp
rbp-8   local variable "sp"
rbp-16  local variable "loc"
rbp-20  local copy of argument "a"
rbp-24  local copy of argument "b"

, a b - 4 , - 8. , C- , *(sp+4) 4 * 8 = 32 bytes not 4, , , .

, :

#include <stdio.h>
#include <stdint.h>
int main();
void func(int a,int b)
{
    uint64_t loc = 0;
    char *sp = (char*)&loc;

    printf("main = %p\n", main);
    printf("return address = %p\n", *(void**)(sp + 24));
    printf("saved rbp = %p\n", *(void**)(sp + 16));
    printf("sp = %p\n", *(void**)(sp + 8));
    printf("loc = %lld\n", *(uint64_t*)(sp));
    printf("a = %d\n", *(int*)(sp - 4));
    printf("b = %d\n", *(int*)(sp - 8));
}

int main()
{
    func(2,3);
    return 0;
}

:

main = 0x4005e6
return address = 0x4005f9
saved rbp = 0x7ffe057bf240
sp = 0x7ffe057bf220
loc = 0
a = 2
b = 3
+3

Source: https://habr.com/ru/post/1621320/


All Articles