GDB: Attempt to dereference generic pointer

35,564

The solution is to cast the pointers before dereferencing them.

For example, picking up where we left off above:

(gdb) x/s **((char ***) (0xc + $ebp))
0xbfffedc8:  "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 1)
0xbfffee03:  "first"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 2)
0xbfffee09:  "second"

Note that the stack address 0xc + $ebp is itself a pointer to the contents of that stack location, and so we need char *** and not char **.

Share:
35,564

Related videos on Youtube

ntc2
Author by

ntc2

https://github.com/ntc2 https://code.google.com/u/nathan.collins https://bitbucket.org/ntc2

Updated on December 06, 2020

Comments

  • ntc2
    ntc2 over 3 years

    How can I make GDB do extra dereferences in a printing function like x/s?

    When I try explicit dereferences in x/ I get the error "Attempt to dereference a generic pointer". Using x/ multiple times works, since each use includes an implicit dereference, but this is annoying since I have to copy and paste each intermediate result.

    Example

    Consider the very useful C program, example.c:

    #include <stdio.h>
    int main(int argc, char **argv) {
      printf("argv[0] = %s\n", argv[0]);
    }
    

    If I build it and load it into GDB, I see that argv is stored at 0xc(%ebp), since a double dererence of that is passed as the second argument to printf (i.e. in 0x4(%esp)) on line 26:

    $ gcc -o example example.c
    $ gdb example
    
    (gdb) disass main
    Dump of assembler code for function main:
       0x080483e4 <+0>:   push   %ebp
       0x080483e5 <+1>:   mov    %esp,%ebp
       0x080483e7 <+3>:   and    $0xfffffff0,%esp
       0x080483ea <+6>:   sub    $0x10,%esp
       0x080483ed <+9>:   mov    0xc(%ebp),%eax
       0x080483f0 <+12>:  mov    (%eax),%edx
       0x080483f2 <+14>:  mov    $0x80484e0,%eax
       0x080483f7 <+19>:  mov    %edx,0x4(%esp)
       0x080483fb <+23>:  mov    %eax,(%esp)
       0x080483fe <+26>:  call   0x8048300 <printf@plt>
       0x08048403 <+31>:  leave  
       0x08048404 <+32>:  ret    
    End of assembler dump.
    

    I break at printf and run the program with arguments first and second:

    (gdb) break *main + 26
    Breakpoint 1 at 0x80483fe
    
    (gdb) run first second
    Starting program: /var/tmp/SO-attempt-to-dereference-generic-pointer/example first second
    

    I attempt to print argv[0] in GDB, but I get the "generic pointer" error:

    Breakpoint 1, 0x080483e5 in main ()
    (gdb) x/s **(0xc + $ebp)
    Attempt to dereference a generic pointer.
    

    However, by using 'x/xw' to manually dereference a few times, I'm eventually able to print argv[0] (and argv[1]):

    (gdb) x/xw 0xc + $ebp
    0xbfffeba4: 0xbfffec34
    (gdb) x/xw 0xbfffec34
    0xbfffec34: 0xbfffedc8
    (gdb) x/s 0xbfffedc8
    0xbfffedc8:  "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
    
    (gdb) x/xw 0xbfffec34 + 4
    0xbfffec38: 0xbfffee03
    (gdb) x/s 0xbfffee03
    0xbfffee03:  "first"
    (gdb) 
    

    But this is annoying and indirect (as pointer programming is wont to be?)

  • Radon Rosborough
    Radon Rosborough almost 4 years
    Why cannot this process be automated by GDB? I know that I'm working with a pointer, otherwise I wouldn't have asked to dereference. Clearly if I ask to dereference again, then the result of the first dereference must be a pointer...