28

I am storing various filenames in my array which are partitioned by null bytes. When debugging, I am only able to see the first filename. So, for instance if my array is like this: hello.txt00000hello2.txt, I am only able to see hello.txt. How can I print the entire array? I have trouble finding such command elsewhere.

4
  • In your example the string is partitioned by a series of 0s, which is not the same as a null byte. Or is that just for illustration purposes? Commented Apr 9, 2015 at 2:36
  • Also, there are many ways of debugging. How is it you print your array? Commented Apr 9, 2015 at 2:44
  • @ReticulatedSpline Its just an illustration. I used memset to set them all to value 0. Commented Apr 9, 2015 at 2:48
  • @Brean I just use print Commented Apr 9, 2015 at 2:48

5 Answers 5

39

With gdb, you can achieve to print the elements of your array using the following command:

(gdb) print *array@size

If my variable array is a type char*[] such as below

const char *array[] = {"first","second","third"};

Then I could display the 2 first char* entries of my array by using:

(gdb) print *array@2
$2 = { 0x..... "first", 0x..... "second"}

Using it in order to display the arguments of a program is very handy:

(gdb) print *argv@argc

It's also possible to do the same with x commands using x/Ns *argv, where N is the integer value of argc (i.e. for argc = 2, x/2s *argv)

The documentation for the whole magic of the print command is here.

Sign up to request clarification or add additional context in comments.

1 Comment

This answer is fantastic. I would like to add a variant in case you want an offset: array[1]@2 would print array[1] and array[2]
32

You can use x/999bc, where 999 is the size of your array, for instance:

paul@thoth:~/src/sandbox$ gdb ./str
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/paul/src/sandbox/str...done.
(gdb) list
1   int main(void) {
2       char * p = "hello\0world\0hahaha";
3       return 0;
4   }
5   
(gdb) b 3
Breakpoint 1 at 0x4004b8: file str.c, line 3.
(gdb) run
Starting program: /home/paul/src/sandbox/str 

Breakpoint 1, main () at str.c:3
3       return 0;
(gdb) print p
$1 = 0x40056c "hello"
(gdb) x/19bc p
0x40056c:   104 'h' 101 'e' 108 'l' 108 'l' 111 'o' 0 '\000'    119 'w' 111 'o'
0x400574:   114 'r' 108 'l' 100 'd' 0 '\000'    104 'h' 97 'a'  104 'h' 97 'a'
0x40057c:   104 'h' 97 'a'  0 '\000'
(gdb) 

Comments

2

If you have a fixed-length array and want to see all the data in there - just ask to print the array and you will get the full output, because GDB knows about the size.
If you have a pointer to a fixed-length array then GDB assumes the most common case - a C string, so it stops the display at the first hex null. To see more: de-reference and cast the result as char array with the intended length you want to see.

#include <stdio.h>
static char myarr[55] = "hello.txt\x00\x00\x00\x000hello2.txt";

int main () {
   char *p = myarr;
   puts (p);
   return 0;
}

compiled and run as gcc -g test.c && gdb -q -ex start ./a.out:

Reading symbols from /tmp/a.out...done.
Temporary breakpoint 1 at 0x400535: file test.c, line 5.
Starting program: /tmp/a.out

Temporary breakpoint 1, main () at test.c:5
5          char *p = myarr;
(gdb) step
6          puts (p);
(gdb) print p
$1 = 0x601060 <myarr> "hello.txt"
(gdb) print *p
$2 = 104 'h'
(gdb) print (char[20])*p
$3 = "hello.txt\000\000\000\000hello2."
(gdb) print (char[55])*p
$4 = "hello.txt\000\000\000\000hello2.txt", '\000' <repeats 31 times>
(gdb) detach
Detaching from program: /tmp/a.out, process 456
hello.txt
(gdb) quit

If you want that to print the sequences in hex instead of in octal - have a look at 54469844.

2 Comments

does that work with dynamic size? print (char[$eax])*($rbx) is a syntax error. there seems to be no eval in gdb... currently i use p/x *($rbx)@$eax but thats verbose
You can at least use python commands and do this multi-step (evaluating both expressions), possibly there's even an option to just read the value "differently" - but with plain print that's not possible (the p/x does work). The print ... @ may also work - see stackoverflow.com/questions/70545366.
1

you might try defining the array as:

char ** array;

array = malloc( NUM_ROWS*sizeof char* );
for( int i =0; i < NUM_ROWS; i++ )
{
    *array[i] = malloc( NUM_COLUMNS )
} 

then the code can

memset( array[x], '\0', NUM_COLUMNS );
strncpy(array[x], myString, NUM_COLUMNS-1);

where myString is the data to place in that row and

for( int i = 0; i < NUM_ROWS; i++ )
{
    if( array[i] )
    { // only enters this code block if something placed in row
        printf( "%s\n", array[x] );
    }
}

then use 'p array[x]' for each row in the array

1 Comment

of course, the code also needs to check the returned value of each malloc to assure the operation was successful and at the end of the code pass each row address to free then pass the array to free
1

sometimes it could be:

x/10bs  array@10 

x/10bc  array@10
  • I debugged corefile and got "Cannot access memory at address" for any other options

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.