Here is my codes:
#include <stdio.h>
int main()
{
fopen("./1.txt","r");
printf("hello");
return 0;
}
$g++ -g -o m main.cpp
$gdb ./m
(gdb) b fopen
Breakpoint 1 at 0x804842c
(gdb) b printf
Breakpoint 2 at 0x804843c
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0804842c <fopen#plt>
2 breakpoint keep y 0x0804843c <printf#plt>
(gdb) r
it seems that the breakpoint at function fopen never work ,but at printf works fine.
why?
Thanks
It's a bug in GDB, which appears to be fixed in current CVS sources (as of 20120124).
The problem is that there are two versions of fopen in 32-bit libc.so.6 on Linux, and GDB used to select the wrong one:
nm -D /lib32/libc.so.6 | grep '\<fopen\>'
0005d0c0 T fopen
00109750 T fopen
readelf -s /lib32/libc.so.6 | egrep '0005d0c0|00109750'
181: 0005d0c0 50 FUNC GLOBAL DEFAULT 12 fopen##GLIBC_2.1
182: 00109750 136 FUNC GLOBAL DEFAULT 12 fopen#GLIBC_2.0
679: 0005d0c0 50 FUNC GLOBAL DEFAULT 12 _IO_fopen##GLIBC_2.1
680: 00109750 136 FUNC GLOBAL DEFAULT 12 _IO_fopen#GLIBC_2.0
If you also break on main, and repeat info break, you'll see that GDB set the breakpoint on fopen#GLIBC_2.0, but the function that is called is the fopen##GLIBC_2.1.
Related
I have this program:
double t;
main() {
}
On Ubuntu, I run:
% gdb a.out
(gdb) p &t
$1 = (double *) 0x4010 <t>
(gdb) run
Starting program: /home/phan/a.out
[Inferior 1 (process 95930) exited normally]
(gdb) p &t
$2 = (double *) 0x555555558010 <t>
Why did the address change from 0x4010 to 0x555555558010. Is there someway to prevent this?
On Redhat, it doesn't do that:
% gdb a.out
(gdb) p &t
$1 = (double *) 0x601038 <t>
(gdb) r
Starting program: /home/phan/a.out
[Inferior 1 (process 23337) exited normally]
(gdb) p &t
$2 = (double *) 0x601038 <t>
BTW, this only occurs in Ubuntu 18.04. In Ubuntu 16.04, it works exactly as Redhat, for example the address is the same before and after.
You are presumably seeing pre and post-relocation addresses for the .bss segment.
You can avoid this by disabling position independent executables, thus making gcc choose the final address of the .bss register up front:
gcc -no-pie foo.c
-static would have the effect.
I don't know why there'd be a difference between Ubuntu and Redhat though.
I am trying to understand how readelf utility calculates function size. I wrote a simple program
#include <stdio.h>
int main() {
printf("Test!\n");
}
Now to check function size I used this (is this OK ? ):
readelf -sw a.out|sort -n -k 3,3|grep FUNC
which yielded:
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts#GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main#GLIBC_2.2.5 (2)
29: 0000000000400470 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
30: 00000000004004a0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
31: 00000000004004e0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
34: 0000000000400500 0 FUNC LOCAL DEFAULT 13 frame_dummy
48: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts##GLIBC_2.2.5
50: 00000000004005b4 0 FUNC GLOBAL DEFAULT 14 _fini
51: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main##GLIBC_
58: 0000000000400440 0 FUNC GLOBAL DEFAULT 13 _start
64: 00000000004003e0 0 FUNC GLOBAL DEFAULT 11 _init
45: 00000000004005b0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
60: 000000000040052d 16 FUNC GLOBAL DEFAULT 13 main
56: 0000000000400540 101 FUNC GLOBAL DEFAULT 13 __libc_csu_init
Now if I check the main function's size, it shows 16. How did it arrive at that? Is that the stack size ?
Compiler used gcc version 4.8.5 (Ubuntu 4.8.5-2ubuntu1~14.04.1)
GNU readelf (GNU Binutils for Ubuntu) 2.24
ELF symbols have an attribute st_size which specifies their size (see <elf.h>):
typedef struct
{
...
Elf32_Word st_size; /* Symbol size */
...
} Elf32_Sym;
This attribute is generated by the toolchain generating the binary; e.g. when looking at the assembly code generated by the C compiler:
gcc -c -S test.c
cat test.s
you will see something like
.globl main
.type main, #function
main:
...
.LFE0:
.size main, .-main
where .size is a special as pseudo op.
update:
.size is the size of the code.
Here, .size gets assigned the result of . - main, where "." is the actual address and main the address where main() starts.
In the 'cat test.s' output provided by ensc, the "secret sauce" is the "..." between 'main:' and '.LFE0:'; those are the assembly instructions generated by the compiler that implement the call to printf(). The corresponding machine code for each assembler instruction occupies some number of bytes; "." is incremented by the number of bytes used by each instruction, so at the end of main, ". - main" is the total number of bytes occupied by the machine instructions for main().
It's the compiler that determines which sequences of assembly instructions are needed to execute the printf() call, and that varies from target to target, and from optimization level to optimization level. In your case, your compiler generated machine code occupying 16 bytes. The '.size main, . - main' caused the assembler to create the ELF symbol for main() with its st_size field set to 16.
readelf read the ELF symbol for main, saw that its st_size field was 16, and dutifully reported 16 as the size for main(). readelf doesn't 'calculate' a function's size -- it just reports the st_size field for the function's ELF symbol. The calculation is done by the assembler, when it interprets the '.size main, . - main' directive.
I'm using gdb.
I run a command like the below to set up the program by sending it input to stdin:
r < <(python -c "print '1\n2\n3'")
I want that command to allow me to start typing input after it finishes (so I can interact with the debugee normally) instead of stdin being closed.
This would work in bash but you can't pipe to the gdb r command this way:
cat <(python -c "print '1\n2\n3'") - | r
The below doesn't work, I assume it waits for EOF before it sends it to the program.
r < <(cat <(python -c "print '1\n2\n3'") -)
Is there a third option that will work?
This sounds like a job for expect.
Given
#include <stdio.h>
int main()
{
char *cp = NULL;
size_t n = 0;
while(getline(&cp, &n, stdin) >= 0) {
fprintf(stderr, "got: %s", cp);
}
return 0;
}
gcc -g -Wall t.c
And this expect script:
#!/usr/bin/expect
spawn gdb -q ./a.out
send run\n
send 1\n2\n3\n
interact
Here is the session:
$ ./t.exp
spawn gdb -q ./a.out
run
1
2
3
Reading symbols from ./a.out...done.
(gdb) run
Starting program: /tmp/a.out
got: 1
got: 2
got: 3
Now the script is waiting for my input. I provide some:
foo bar baz
got: foo bar baz
I can also interact with GDB:
^C
Program received signal SIGINT, Interrupt.
0x00007ffff7b006b0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0 0x00007ffff7b006b0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007ffff7a8f5a0 in _IO_new_file_underflow (fp=0x7ffff7dd4640 <_IO_2_1_stdin_>) at fileops.c:613
#2 0x00007ffff7a840d5 in _IO_getdelim (lineptr=0x7fffffffdda0, n=0x7fffffffdda8, delimiter=10, fp=0x7ffff7dd4640 <_IO_2_1_stdin_>) at iogetdelim.c:77
#3 0x000000000040064e in main () at t.c:9
I was trying to learn how to use rbp/ebp to visit function parameters and local variables on ubuntu1604, 64bit. I've got a simply c file:
#include<stdio.h>
int main(int argc,char*argv[])
{
printf("hello\n");
return argc;
}
I compiled it with:
gcc -g my.c
Then debug it with argument parameters:
gdb --args my 01 02
Here I know the "argc" should be 3, so I tried to check:
(gdb) b main
Breakpoint 1 at 0x400535: file ret.c, line 5.
(gdb) r
Starting program: /home/a/cpp/my 01 02
Breakpoint 1, main (argc=3, argv=0x7fffffffde98) at ret.c:5
5 printf("hello\n");
(gdb) x $rbp+4
0x7fffffffddb4: 0x00000000
(gdb) x $rbp+8
0x7fffffffddb8: 0xf7a2e830
(gdb) x/1xw $rbp+8
0x7fffffffddb8: 0xf7a2e830
(gdb) x/1xw $rbp+4
0x7fffffffddb4: 0x00000000
(gdb) x/1xw $rbp
0x7fffffffddb0: 0x00400550
I don't find any clue that a dword of "3" is saved in any of bytes in $rbp+xBytes. Did I get anything wrong in my understanding or commands?
Thanks!
I was trying to learn how to use rbp/ebp to visit function parameters and local variables
The x86_64 ABI does not use stack to pass parameters; they are passed in registers. Because of that, you wouldn't find them at any offset off $rbp (this is different from ix86 calling convention).
To find the parameters, you'll need to look at the $rdi and $rsi regusters:
Breakpoint 1, main (argc=3, argv=0x7fffffffe3a8) at my.c:4
4 printf("hello\n");
(gdb) p/x $rdi
$1 = 0x3 # matches argc
(gdb) p/x $rsi
$2 = 0x7fffffffe3a8 # matches argv
x $rbp+4
You almost certainly wouldn't find anything useful at $rbp+4, because it is usually incremented or decremented by 8, in order to store the entire 64-bit value.
For controlling output on Linux there is control-s and control-t, which provides a method for temporarily halting terminal output and then resuming it. On VMS in addition there was control-O, which would toggle all output on and off. This didn't pause output, it discarded it.
Is there an equivalent keyboard shortcut in Linux?
This comes up most often for me in gdb, when debugging programs which output millions of status lines. It would be very convenient to be able to temporarily send most of that to /dev/null rather than the screen, and then pick up with the output stream further on, having dispensed with a couple of million lines in between.
(Edited: The termios(3) man page mentions VDISCARD - and then says that it isn't going to work in POSIX or Linux. So it looks like this is out of the question for general command line use on linux. gdb might still be able to discard output though, through one of its own commands. Can it?)
Thanks.
On VMS in addition there was control-O ...
This functionality doesn't appear to exist on any UNIX system I've ever dealt with (or maybe I just never knew it existed; it's documented in e.g. FreeBSD man page, and is referenced by Solaris and HP-UX docs as well).
gdb might still be able to discard output though, through one of its own commands. Can it?
I don't believe so: GDB doesn't actually intercept the output from the inferior (being debugged) process, it simply makes it run (between breakpoints) with the inferior output going to wherever it's going.
That said, you could do it yourself:
#include <stdio.h>
int main()
{
int i;
for (i = 0; i < 1000; ++i) {
printf("%d\n", i);
}
}
gcc -g foo.c
gdb -q ./a.out
(gdb) break 6
Breakpoint 1 at 0x40053e: file foo.c, line 6.
(gdb) run 20>/dev/null # run the program, file descriptor 20 goes to /dev/null
Starting program: /tmp/a.out 20>/dev/null
Breakpoint 1, main () at foo.c:6
6 printf("%d\n", i);
(gdb) c
Continuing.
0
Breakpoint 1, main () at foo.c:6
6 printf("%d\n", i);
We've now run two iterations. Let's prevent further output for 100 iterations:
(gdb) call dup2(20, 1)
$1 = 1
(gdb) ign 1 100
Will ignore next 100 crossings of breakpoint 1.
(gdb) c
Continuing.
Breakpoint 1, main () at foo.c:6
6 printf("%d\n", i);
(gdb) p i
$2 = 102
No output, as desired. Now let's restore output:
(gdb) call dup2(2, 1)
$3 = 1
(gdb) ign 1 10
Will ignore next 10 crossings of breakpoint 1.
(gdb) c
Continuing.
102
103
104
105
106
107
108
109
110
111
112
Breakpoint 1, main () at foo.c:6
6 printf("%d\n", i);
Output restored!