Search code examples
assemblygdbatt

Examining strings using gdb


I would like to know how to view command line arguments passed to a function using gdb.

To test this I compiled the following code

.global main
main:
    pushl %ebp
    movl %esp, %ebp
    movl $1, %eax
    movl $0, %ebx
    int $0x80

with

gcc -Wall -Wextra -g -m32 args.s

to invoke the assembler and linker.

My System is x86_64 ubuntu (but for learning I Started with creating 32 bit applications).

I launched gdb and passed 2 command line arguments with

start test 12345

At this point I expected the stack to look like this:

  • Address argument 2 <-- $ebp+20
  • Address argument 1 <-- $ebp+16
  • Address name of programm <-- $ebp+12
  • argc <-- $ebp+8
  • old eip <-- $ebp+4
  • old ebp <-- $ebp

Reading the argument counter

(gdb) x /d $ebp+8

gives the expected Output:

0xffffd110: 3

Now I tried to check the command line arguments which have been passed. I expected

x /x $ebp+16

to give the address of the first character of the first passed argument in memory. The output was:

0xffffd118: 0xb4

But When I tried to access that region

(gdb) x /x 0xb4

I got:

0xb4:   Cannot access memory at address 0xb4

Which leads me to the conclusion that I tried to access a location which is different from the location where my commandline arguments are stored.

Can anyone give me some pointers to the true location of the command line arguments?


Solution

  • The main function of C gets the arguments in a different manner than the first called function of the Linux loader. Recapitulate the declaration of main in C: int main(int argc, char *argv[]) (as mentioned in the standard). The main function will get a value and a pointer to an array of strings, i.e. a pointer to several pointers to a string.

    Tl;dr:

    argc: x /d $ebp+8
    argv[0]: x /s **(int)($ebp+12)
    argv[1]: x /s *(*(int)($ebp+12)+4)
    argv[2]: x /s *(*(int)($ebp+12)+8)