Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
283 views
in Technique[技术] by (71.8m points)

c - What exactly is -fno-builtin doing here?

So I was reading Hacking the Art of Exploitation and in the book, they use the strcpy() function in their C code:

1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!
");
8           printf(str_a);
9       }

They then proceed to compile their source code and analyze it with gdb. He sets a breakpoint on line 6, the strcpy function, and line 8, but when setting a break on strcpy it reads the following:

(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

I understand that this is because the library has not yet been loaded, so it's asking if he wants to have it as a pending breakpoint. Then he runs the program and continues through the breakpoints:

image

Everything works well for him, but when I tried to re-create this on my computer, I get the following:

frinto@kali:~/Documents/theclang/programs/helloworld$ gcc -m32 -g -o char_array char_array.c 
frinto@kali:~/Documents/theclang/programs/helloworld$ gdb -q char_array
Reading symbols from char_array...done.
(gdb) list
1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!
");
8           printf(str_a);
9       }
(gdb) break 6
Breakpoint 1 at 0x11b6: file char_array.c, line 6.
(gdb) break strcpy
Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (strcpy) pending.
(gdb) break 8
Breakpoint 3 at 0x11d7: file char_array.c, line 8.
(gdb) run
Starting program: /home/frinto/Documents/theclang/programs/helloworld/char_array 

Breakpoint 1, main () at char_array.c:7
7           strcpy(str_a, "Hello, world!
");
(gdb) cont
Continuing.

Breakpoint 3, main () at char_array.c:8
8           printf(str_a);
(gdb) cont
Continuing.
Hello, world!
[Inferior 1 (process 4021) exited normally]
(gdb) 

Notice how it completely skipped the strcpy breakpoint? Well, I asked a friend of mine what was the issue here, and he told me that I was missing the argument -fno-builtin when compiling. I did some minimal google searching on this argument and all I really understood is that it lets you set breakpoints on built-in functions. So I compiled the program with the -fno-builtin argument and then tried to re-create this again:

frinto@kali:~/Documents/theclang/programs/helloworld$ gcc -m32 -fno-builtin -g -o char_array char_array.c 
frinto@kali:~/Documents/theclang/programs/helloworld$ gdb -q char_array
Reading symbols from char_array...done.
(gdb) list
1   #include <stdio.h>
2   #include <string.h>
3   
4       int main() {
5           char str_a[20];
6   
7           strcpy(str_a, "Hello, world!
");
8           printf(str_a);
9       }
(gdb) break 6
Breakpoint 1 at 0x11c6: file char_array.c, line 6.
(gdb) break strcpy
Breakpoint 2 at 0x1040
(gdb) break 8
Breakpoint 3 at 0x11dc: file char_array.c, line 8.
(gdb) run
Starting program: /home/frinto/Documents/theclang/programs/helloworld/char_array 

Breakpoint 1, main () at char_array.c:7
7           strcpy(str_a, "Hello, world!
");
(gdb) cont
Continuing.

Breakpoint 2, 0xf7e510b0 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) cont
Continuing.

Breakpoint 3, main () at char_array.c:8
8           printf(str_a);
(gdb) cont
Continuing.
Hello, world!
[Inferior 1 (process 3969) exited normally]
(gdb) 

Now it works! I have three questions:

  1. What exactly is the -fno-builtin argument doing?
  2. Why does it show question marks instead of the strcpy function in

Breakpoint 2, 0xf7e510b0 in ?? () from /lib/i386-linux-gnu/libc.so.6

  1. Why doesn't it ask to set the strcpy breakpoint as pending when I use the -fno-builtin argument?

Sorry for the long thread, I just wanted to make sure everything was understood.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

From man gcc

-fno-builtin
-fno-builtin-function

   Don't recognize built-in functions that do not begin with
   __builtin_ as prefix.  GCC normally generates special code to
   handle certain built-in functions more efficiently; for
   instance, calls to "alloca" may become single instructions
   which adjust the stack directly, and calls to "memcpy" may
   become inline copy loops.  The resulting code is often both
   smaller and faster, but since the function calls no longer
   appear as such, you cannot set a breakpoint on those calls, nor
   can you change the behavior of the functions by linking with a
   different library.  In addition, when a function is recognized
   as a built-in function, GCC may use information about that
   function to warn about problems with calls to that function, or
   to generate more efficient code, even if the resulting code
   still contains calls to that function.  For example, warnings
   are given with -Wformat for bad calls to "printf" when "printf"
   is built in and "strlen" is known not to modify global memory.

   With the -fno-builtin-function option only the built-in
   function function is disabled.  function must not begin with
   __builtin_.  If a function is named that is not built-in in
   this version of GCC, this option is ignored.  There is no
   corresponding -fbuiltin-function option; if you wish to enable
   built-in functions selectively when using -fno-builtin or
   -ffreestanding, you may define macros such as:

           #define abs(n)          __builtin_abs ((n))
           #define strcpy(d, s)    __builtin_strcpy ((d), (s))

function builtins allow to generate a faster code by inlining the function, but as stated in the manual

you cannot set a breakpoint on those calls

Inlining a function means that, instead of generating a function call, its effects are replaced by code directly inserted by the compiler. This saves a function call and can be more efficiently optimized and generally leads to a large improvement in performances.

But, the inlined function no longer exists in the code. Debugger breakpoints are implemented by replacing instructions at specific addresses by some software traps or by using specific hardware to recognize when the breakpointed address is reached. But as the function no longer exists, no address is associated with it, and there is no way to breakpoint it.

Pending breakpoints are a mean to set a breakpoint on some code that will be dynamically loaded later by the program. With -fno-builtin, strcpy is directly available and the bp can be directly set by gdb.

Note that debugging requires specific information in the executable generated by the -g flag. Generally system libraries like libc do not have the debugging information embedded and when entering function in these libraries, gdb indicates the lack of debugging information by ??.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...