Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

accessing command-line arguments with gdb

Tags:

c

assembly

gdb

I am on linux using gdb version 6.8-debian. I have been curious about how the main function in a c-program gets executed and playing around and looking in different places, I learned that the function __libc_start_main is responsiple for this. The arguments to __libc_start_main are, among others: The address of main (like we know from c, the path is always given as argv[0]), next argc which should reside in the register ESI, and next address of argv which should be in ECX.

To play around I made the following simple program, cmdargs.c, which simply outputs the first command-line argument given at start:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
    printf("%s: %s\n", "argv[1]", *++argv);
    return EXIT_SUCCESS;
}

Now I start to debug cmdargs and set a breakpoint on main and __libc_start_main (info from starting gdb removed):

gdb cmdargs

(gdb) b main
Breakpoint 1 at 0x80483d2
(gdb) b __libc_start_main
Breakpoint 2 at 0xb7f3f5a8
(gdb) r qwerty

Here i hit the Breakpoint 2 in __libc_start_main and can view argc and argv[0] with

(gdb) p $esi

and

(gdb) x/s *($ecx)

This works as expected, but how do I access the first non-implicit commandline-argument "qwerty" ? I have tried continuing to the breakpoint at main and stepping in, but argc and argv are not recognised (Why?). Can someone tell me whats going on ?

Breakpoint 1, 0x080483d2 in main ()
(gdb) stepi
0x080483d5 in main () 
(gdb) p argc
No symbol "argc" in current context.
(gdb) p argv
No symbol "argv" in current context.
(gdb) 
like image 905
MicBoehm Avatar asked Nov 25 '10 14:11

MicBoehm


People also ask

How do I pass command line arguments to GDB?

You can optionally have gdb pass any arguments after the executable file to the inferior using --args . This option stops option processing. This will cause gdb to debug gcc , and to set gcc 's command-line arguments (see Arguments) to ` -O2 -c foo. c '.

How do I run a command in GDB?

Starting your program. Use the run command to start your program under GDB. You must first specify the program name (except on VxWorks) with an argument to GDB (see section Getting In and Out of GDB), or by using the file or exec-file command (see section Commands to specify files).

How do I get thread info in GDB?

Use the "info threads" command to see the IDs of currently known threads. The GDB thread debugging facility allows you to observe all threads while your program runs--but whenever GDB takes control, one thread in particular is always the focus of debugging. This thread is called the current thread.

Can you call functions in GDB?

To call a function in the program, GDB has to temporarily modify the state of the inferior. This has potentially undesired side effects. Also, having GDB call nested functions is likely to be erroneous and may even crash the program being debugged.


3 Answers

Yep, your problem is the lack of symbols, not included at compilation time.

To compile with debugging information:

$ gcc -g3 cmdargs.c -o cmdargs

Then:

$ gdb ./cmdargs
...
Reading symbols from ./cmdargs...done.
(gdb) b main
Breakpoint 1 at 0x400545: file cmdargs.c, line 6.
(gdb) r
Starting program: cmdargs 

Breakpoint 1, main (argc=1, argv=0x7fffffffdc28) at cmdargs.c:6
6       printf("%s: %s\n", "argv[1]", *++argv);
(gdb) p argc
$1 = 1
(gdb) p argv
$2 = (char **) 0x7fffffffdc28
(gdb) p *argv
$3 = 0x7fffffffe00c "/home/jcgonzalez/cmdargs"

See, now you get access to the symbols (they are recognized), as well as to the line numbers. As shown by Let_Me_Be, you can access single array elements with array[n] notation, but you can also show all the command line arguments at once (including the [0]-ed one) with the *array@times notation. Note that the first argument in the following example is a quoted string:

(gdb) set args "this is an argument" these are four more 
(gdb) r
Starting program: cmdargs "this is an argument" these are four more

Breakpoint 1, main (argc=6, argv=0x7fffffffdbd8) at cmdargs.c:6
6       printf("%s: %s\n", "argv[1]", *++argv);
(gdb) p argc
$4 = 6
(gdb) p *argv@argc                                    
$5 = {0x7fffffffdfe6 "/home/jcgonzalez/cmdargs", 0x7fffffffdfff "this is an argument", 0x7fffffffe012 "these", 0x7fffffffe017 "are", 0x7fffffffe01b "four", 
  0x7fffffffe020 "more"}
(gdb) p argv[1]
$6 = 0x7fffffffdfff "this is an argument"
(gdb) p argv[2]
$7 = 0x7fffffffe012 "these"
like image 187
J C Gonzalez Avatar answered Sep 29 '22 20:09

J C Gonzalez


The output looks as if you don't have enough debuging information. GDB shouldn't print only addresses but line numbers as well.

(gdb) b main
Breakpoint 1 at 0x400543: file test.c, line 3.
(gdb) r test1 test2
Starting program: /home/simon/a.out test1 test2

Breakpoint 1, main (argc=3, argv=0x7fffffffdca8) at test.c:3
3               puts("blabla");
(gdb) print argc
$1 = 3
(gdb) print argv
$2 = (char **) 0x7fffffffdca8
(gdb) print argv[0]
$3 = 0x7fffffffe120 "/home/simon/a.out"
(gdb) print argv[1]
$4 = 0x7fffffffe132 "test1"
(gdb) print argv[2]
$5 = 0x7fffffffe138 "test2"
(gdb)
like image 34
Šimon Tóth Avatar answered Sep 29 '22 20:09

Šimon Tóth


you should add the -g options to gcc, which tells it to build debug info too..

like image 33
BlackBear Avatar answered Sep 29 '22 20:09

BlackBear