When I examine memory with x, I can see the symbol of the address I am reading:
(gdb) x/16zw &pt_table
0x102000 <pt_table>: 0x00000000 0x00000000 0x00000000 0x00000000
0x102010: 0x00000000 0x00000000 0x00000000 0x00000000
How can I disable the printing of the label (or move to its own line) so the data is correctly aligned? I cannot find anything on the manual.
Example:
(gdb) x/16zw &pt_table
0x102000: 0x00000000 0x00000000 0x00000000 0x00000000
0x102010: 0x00000000 0x00000000 0x00000000 0x00000000
Or:
(gdb) x/16zw &pt_table
<pt_table>:
0x102000: 0x00000000 0x00000000 0x00000000 0x00000000
0x102010: 0x00000000 0x00000000 0x00000000 0x00000000
How can I disable the printing of the label (or move to its own line) so the data is correctly aligned?
I looked at the current GDB source (print_address_symbolic) and there isn't any way to suppress printing of the symbol or symbol+offset.
Maybe you want to use LLDB instead.
(gdb) list
1 int abc[100];
2 int main() { return abc[2]; }
(gdb) start
Temporary breakpoint 1 at 0x1129: file t.c, line 2.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at t.c:2
2 int main() { return abc[2]; }
(gdb) x/8x &abc[1]
0x555555558064 <abc+4>: 0x00000000 0x00000000 0x00000000 0x00000000
0x555555558074 <abc+20>: 0x00000000 0x00000000 0x00000000 0x00000000
Compare to LLDB:
(lldb) run
Process 3645824 launched: '/tmp/a.out' (x86_64)
Process 3645824 stopped
* thread #1, name = 'a.out', stop reason = breakpoint 1.1
frame #0: 0x0000555555555129 a.out`main at t.c:2:24
1 int abc[100];
-> 2 int main() { return abc[2]; }
(lldb) x/8x &abc[1]
0x555555558064: 0x00000000 0x00000000 0x00000000 0x00000000
0x555555558074: 0x00000000 0x00000000 0x00000000 0x00000000
Related
The following code crashes in 64 bit system. If file name length is less than 3,
then underflow happen for the 'len'. But this program is not showing any
segmentation fault in 32 bit system. But I am getting segmentation fault in 64
bit system. Why This program is not showing any segmentation fault in 32 bit
system ?
DIR * dirp = opendir(dirPath);
struct dirent * dp;
while(dirp)
{
if((dp = readdir(dirp)) != NULL)
{
unsigned int len = strlen(dp->d_name);
//underflow happens if filename length less than 3
if((dp->d_name[len - 3] == 'j'))
}
}
You program results in undefined behaviour, as you appear to be aware of. You are attempting to access outside the bounds of the array. And undefined behaviour is just what it sounds like. The behaviour is not defined. Anything could happen.
You might get a segmentation fault one time you run, and not another time. Or you might see different behaviour under different compilers. Undefined behaviour is by its very nature unpredictable. The fact that you seemed to get away with this error in your code under one compiler does not make your code correct.
Obviously what you should do is to avoid writing programs that result in undefined behaviour.
Why This program is not showing any segmentation fault in 32 bit system ?
Look, this is slightly simplified your program:
1 int main(int argc, char *argv[])
2 {
3 char name[100];
4 unsigned int len = 3;
5 name[len-argc] = 1;
6 return 0;
7 }
So when I build it as 32-bit program gcc -m32 -g main.c -o main32 this is how under gdb the address space of a process looks:
$ gdb -q --args ./main32 1 2 3
Reading symbols from /home/main32...done.
(gdb) start
(gdb) info proc mappings
process 28330
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x110000 0x111000 0x1000 0x0 [vdso]
0x3fa000 0x418000 0x1e000 0x0 /lib/ld-2.12.so
0x418000 0x419000 0x1000 0x1d000 /lib/ld-2.12.so
0x419000 0x41a000 0x1000 0x1e000 /lib/ld-2.12.so
0x41c000 0x5a8000 0x18c000 0x0 /lib/libc-2.12.so
0x5a8000 0x5aa000 0x2000 0x18c000 /lib/libc-2.12.so
0x5aa000 0x5ab000 0x1000 0x18e000 /lib/libc-2.12.so
0x5ab000 0x5ae000 0x3000 0x0
0x8048000 0x8049000 0x1000 0x0 /home/main32
0x8049000 0x804a000 0x1000 0x0 /home/main32
0xf7fdf000 0xf7fe0000 0x1000 0x0
0xf7ffd000 0xf7ffe000 0x1000 0x0
0xfffe9000 0xffffe000 0x15000 0x0 [stack]
(gdb) p/x &(name[len-argc])
$2 = 0xffffcfab
As you can see name[3-4] (it is underflow as you say) actually points to a valid address on stack. This is why your process does not crash.
When I build the same program as 64 bit (gcc -m64 -g main.c -o main64) the address will not be valid
(gdb) info proc mappings
process 29253
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x400000 0x401000 0x1000 0x0 /home/main64
0x600000 0x601000 0x1000 0x0 /home/main64
0x3c40a00000 0x3c40a20000 0x20000 0x0 /lib64/ld-2.12.so
0x3c40c1f000 0x3c40c20000 0x1000 0x1f000 /lib64/ld-2.12.so
0x3c40c20000 0x3c40c21000 0x1000 0x20000 /lib64/ld-2.12.so
0x3c40c21000 0x3c40c22000 0x1000 0x0
0x3c41200000 0x3c41389000 0x189000 0x0 /lib64/libc-2.12.so
0x3c41389000 0x3c41588000 0x1ff000 0x189000 /lib64/libc-2.12.so
0x3c41588000 0x3c4158c000 0x4000 0x188000 /lib64/libc-2.12.so
0x3c4158c000 0x3c4158d000 0x1000 0x18c000 /lib64/libc-2.12.so
0x3c4158d000 0x3c41592000 0x5000 0x0
0x7ffff7fdd000 0x7ffff7fe0000 0x3000 0x0
0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x0
0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0 [vdso]
0x7ffffffea000 0x7ffffffff000 0x15000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
(gdb) p/x &name[len-argc]
$5 = 0x8000ffffde3f
One more thing. This is how assembler looks for 64-bit application:
(gdb) disassemble /m
Dump of assembler code for function main:
5 name[len-argc] = 1;
0x0000000000400472 <+22>: mov -0x74(%rbp),%edx
0x0000000000400475 <+25>: mov -0x4(%rbp),%eax
0x0000000000400478 <+28>: sub %edx,%eax
0x000000000040047a <+30>: mov %eax,%eax
=> 0x000000000040047c <+32>: movb $0x1,-0x70(%rbp,%rax,1)
This is $eax::
(gdb) p $eax
$1 = -1
But assigning use rax since you are in 64 mode. And this is the value of $rax:
(gdb) p/x $rax
$3 = 0xffffffff
So the program adds to a valid stack addres a huge positive offset and it results in invalid address.
I would like to underline that this is undefined behavior in both 32 and 64 modes. If you want to fix this undefined behavior you can read my another answer https://stackoverflow.com/a/24287919/184968.
dp->d_name[len - 3] == 'j' the len - 3 might be within your segment on this 32-bit machine and just outside your segment on the 64-bit machine. It has to do with your operating system.
I have an library that don't give correct output. I guess it is possibly an write violation, and focused it on this section of code:
void Page::build_default_frame(PosType genome_display_length)
{
Frame* frame = new Frame(*this,
margin_left,
margin_top,
width - margin_left - margin_right,
genome_display_length);
default_frame = frame;
frames.insert(default_frame);
}
The default_frame is a boost intrusive_ptr<Frame>.
Before execute the sentence default_frame = frame, the content of object frame was all right, but after that, its contents were modified to weird value. So I set two watches on two member variables of frame object:
(gdb) watch -l frame->genome_scale.genome_display_length
Hardware watchpoint 4: -location frame->genome_scale.genome_display_length
(gdb) watch -l frame->genome_scale.frame_width
Hardware watchpoint 5: -location frame->genome_scale.frame_width
and then continue. It suddenly reports write operation on these address:
(gdb) c
Continuing.
Hardware watchpoint 4: -location frame->genome_scale.genome_display_length
Old value = 1000
New value = 16
_dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:39
39 ../sysdeps/x86_64/dl-trampoline.S: No such file or directory.
(gdb) bt
#0 _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:39
#1 0x00007ffff7b93dd0 in geno_eye::Page::build_default_frame (this=0x6071b0, genome_display_length=1000)
at /home/yangxi/projects/GenoEye/src/geno_eye/Page.cpp:127
#2 0x00007ffff7b93cc1 in geno_eye::Page::Page (this=0x6071b0, context=0x607750, width=300, height=300,
genome_display_length=1000) at /home/yangxi/projects/GenoEye/src/geno_eye/Page.cpp:29
#3 0x00000000004016b8 in geno_eye::__tester__::run (this=0x7fffffffe1c8)
at /home/yangxi/projects/GenoEye/t/t_page.cpp:15
#4 0x00000000004015d1 in main () at /home/yangxi/projects/GenoEye/t/t_page.cpp:36
(gdb) c
Continuing.
Hardware watchpoint 5: -location frame->genome_scale.frame_width
Old value = 240
New value = 3.1228427039313504e-317
_dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:40
40 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) bt
#0 _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:40
#1 0x00007ffff7b93dd0 in geno_eye::Page::build_default_frame (this=0x6071b0, genome_display_length=1000)
at /home/yangxi/projects/GenoEye/src/geno_eye/Page.cpp:127
#2 0x00007ffff7b93cc1 in geno_eye::Page::Page (this=0x6071b0, context=0x607750, width=300, height=300,
genome_display_length=1000) at /home/yangxi/projects/GenoEye/src/geno_eye/Page.cpp:29
#3 0x00000000004016b8 in geno_eye::__tester__::run (this=0x7fffffffe1c8)
at /home/yangxi/projects/GenoEye/t/t_page.cpp:15
#4 0x00000000004015d1 in main () at /home/yangxi/projects/GenoEye/t/t_page.cpp:36
The two old values are the correct values for that two member variables. This write operation is happened before executing the = function of boost intrusive_ptr, as I pressed tens of "next", and the code is still in file dl-trampoline.S.
(gdb) n
41 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
42 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
43 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
44 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
45 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
46 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
47 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
48 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
49 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
50 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
51 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
52 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
53 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
54 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
56 in ../sysdeps/x86_64/dl-trampoline.S
(gdb) n
boost::intrusive_ptr<geno_eye::Frame>::operator= (this=0x6071b0, rhs=0x3e8)
at /usr/include/boost/smart_ptr/intrusive_ptr.hpp:134
134 {
What is dl-trampoline.S ? Why it silently write on the memory of my object?
In addition of that, I also run valgrind:
$ valgrind ./t_page
However, instead of invalid write, it reports invalid read to that object, which is happened after the object creation is finished.
This is caused by an reference-to-stack bug.
Object genome_scale holds two references to two member variables of frame object. When I reconstruct my code, it accidentally reference to two stack variables...
So, maybe I should avoid the use of reference types in this situation, as you can easily provide stack stuffs to them and don't get any warns.
I am trying GDB tracepoints, but I can't get any data. I start gdbserver as following:
$ gdbserver :1234 ./a.out
Process ./a.out created; pid = 13610
Listening on port 1234
I then use the following commands on my client:
$ gdb ./a.out
...
Reading symbols from /home/simark/src/test/a.out...done.
(gdb) target remote :1234
Remote debugging using :1234
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.15.so...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007ffff7ddb6c0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) l
1 #include <stdio.h>
2 int foo(int a, int b) {
3 return a + b + b;
4 }
5
6 int main() {
7 int n = foo(33, 4);
8 printf("%d\n", n);
9 return 0;
10 }
(gdb) trace 3
Tracepoint 1 at 0x400526: file test.c, line 3.
(gdb) b 9
Breakpoint 2 at 0x400563: file test.c, line 9.
(gdb) actions 1
Enter actions for tracepoint 1, one per line.
End with a line saying just "end".
>collect $regs,$args
>end
(gdb) tstart
(gdb) c
Continuing.
Breakpoint 2, main () at test.c:9
9 return 0;
(gdb) tstop
(gdb) tdump
warning: No current trace frame.
(gdb)
According to the examples I saw on the web, I should have one event, because control passed over my tracepoint. Any ideas why I get no data?
According to the examples I saw on the web, I should have one event, because control passed over my tracepoint.
You forgot to do tfind start before doing tdump. From help tdump:
Print everything collected at the current tracepoint.
But you are not stopped at any tracepoint, you are stopped at breakpoint#2.
The tfind start selects the first trace frame in the trace buffer.
I am studying the watchpoint of GDB. I write a simple test code as following:
int main(int argc, char **argv)
{
int x = 30;
int y = 10;
x = y;
return 0;
}
I build it via gcc -g -o wt watch.c. And then I started gdb and did following experiment:
lihacker#lihacker-laptop:~/mySrc$ gdb ./wt
GNU gdb (GDB) 7.3
Copyright (C) 2011 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 "i686-pc-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/lihacker/mySrc/wt...done.
(gdb) b main
Breakpoint 1 at 0x80483a5: file watch.c, line 5.
(gdb) run
Starting program: /home/lihacker/mySrc/wt
Breakpoint 1, main (argc=<optimized out>, argv=<optimized out>) at watch.c:5
5 int x = 30;
(gdb) watch x
Hardware watchpoint 2: x
(gdb) c
Continuing.
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
0xb7e83775 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb)
In my test codes, the variable "x" is changed, but gdb doesn't stop then.
Why the watchpoint doesn't effect here? Thanks a lot.
This:
Breakpoint 1, main (argc=<optimized out>, argv=<optimized out>) at watch.c:5
suggests that you used -O2 or some such flag when building the test. Try building with -O0 (which will explicitly disable optimization).
Even then, there is a glitch (a buglet) in GDB. Here is what I see:
(gdb) b main
Breakpoint 3 at 0x80483ba: file t.c, line 3.
(gdb) r
Breakpoint 3, main (argc=1, argv=0xffffca94) at t.c:3
3 int x = 30;
(gdb) watch x
Hardware watchpoint 4: x
(gdb) c
Hardware watchpoint 4: x
Old value = 0
New value = 10
main (argc=1, argv=0xffffca94) at t.c:8
8 return 0;
(gdb) c
Watchpoint 4 deleted because the program has left the block in
which its expression is valid.
0xf7e7cbd6 in __libc_start_main () from /lib32/libc.so.6
This can't be right: the value of x changes from 30 to 10, not from 0 to 10.
If I set the breakpoint on the very first instruction of main, then it works as expected:
(gdb) b *main
Breakpoint 1 at 0x80483b4: file t.c, line 2.
(gdb) r
Breakpoint 1, main (argc=1, argv=0xffffca94) at t.c:2
2 {
(gdb) watch x
Hardware watchpoint 2: x
(gdb) c
Hardware watchpoint 2: x
Old value = 0
New value = 30
main (argc=1, argv=0xffffca94) at t.c:4
4 int y = 10;
(gdb) c
Hardware watchpoint 2: x
Old value = 30
New value = 10
main (argc=1, argv=0xffffca94) at t.c:8
8 return 0;
(gdb) c
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
0xf7e7cbd6 in __libc_start_main () from /lib32/libc.so.6
x/4x xxx will check bytes at higher address than xxx.
How to check bytes at lower address ?
Just subtract the number of preceding bytes you want from xxx:
(gdb) x/4x 0x13b3da00
0x13b3da00: 0x004cc630 0x00000000 0x13af3ba0 0x00000000
(gdb) x/4x 0x13b3da00-4
0x13b3d9fc: 0x00000000 0x004cc630 0x00000000 0x13af3ba0
(gdb) x/4x 0x13b3da00-8
0x13b3d9f8: 0x00000000 0x00000000 0x004cc630 0x00000000