2

Here there is a short snippet of my code:

 //l2tp_inspector.cc
 14   else if (f_info->key.proto == UDP_PROTO) {
 15     if (size >= 4) {
 16       uint32_t l2tp_part;
 17       l2tp_part = *((uint32_t*)(data));
 18 
 19       if ((l2tp_part & 0xFFFF0000) == 0xC802 &&                                                                                                                  
 20           (l2tp_part & 0x0000FFFF) == size) {
 21         f_info->protocol_id = Bina::Protocols::UDP_L2TP;
 22         f_info->application_id = Bina::Applications::UNKNOWN;
 23         return PROTOCOL_ACCEPTED_FINALIZED;
 24       }
 25     }
 26     return REJECTED;
 27   }

After compiling the code and using gdb debugger with break points on lines 17, 18 and 19, we have the following output:

test@ubuntu:~/prj$ gdb prj-loader 

GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git
This GDB was configured as "x86_64-linux-gnu".

(gdb) b l2tp_inspector.cc:17
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (l2tp_inspector.cc:17) pending.

(gdb) b l2tp_inspector.cc:18
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (l2tp_inspector.cc:18) pending.

(gdb) b l2tp_inspector.cc:19
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 3 (l2tp_inspector.cc:19) pending.

(gdb) r
Starting program: ~/prj/prj-loader 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[2017-02-02 08:44:52.267622] [0x00007ffff7fc9780] [info]    New id registered TCP with id 0
[2017-02-02 08:44:52.267899] [0x00007ffff7fc9780] [info]    New id registered TCP_PAYLOAD with id 1
[2017-02-02 08:44:52.267991] [0x00007ffff7fc9780] [info]    New id registered UDP with id 2
[2017-02-02 08:44:52.268025] [0x00007ffff7fc9780] [info]    New id registered UDP_PAYLOAD with id 3
[2017-02-02 08:44:52.268169] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:44:52.268201] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:44:52.268285] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:44:52.268380] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:44:52.268519] [0x00007ffff7fc9780] [info]    New id registered IPV4 with id 4
[2017-02-02 08:44:52.268553] [0x00007ffff7fc9780] [info]    New id registered IPV4FRAG with id 5
[2017-02-02 08:44:52.268632] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:44:52.268715] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:44:52.268795] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:44:52.268877] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:44:52.268972] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:44:52.269066] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:44:52.269149] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:44:52.269229] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:44:52.269370] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:44:52.269401] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:44:52.269481] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:44:52.269561] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:44:52.269643] [0x00007ffff7fc9780] [info]    Already registered id IPV4 with id 4
[2017-02-02 08:44:52.269723] [0x00007ffff7fc9780] [info]    Already registered id IPV4FRAG with id 5
[2017-02-02 08:44:52.269807] [0x00007ffff7fc9780] [info]    New id registered ETHERNET with id 6

Breakpoint 1, inspect (f_info=0x7fffffffce50, data=0x555555be439a "\310\002", size=106, s_module=@0x7fffffffcde0: 0x0)
    at ../src/modules/prj-lib/src/proto-inspectors/l2tp_inspector.cc:17
17        l2tp_part = *((uint32_t*)(data));

(gdb) s
Breakpoint 2, inspect (f_info=0x7fffffffce50, data=0x555555be439a "\310\002", size=106, s_module=@0x7fffffffcde0: 0x0)
    at ../src/modules/prj-lib/src/proto-inspectors/l2tp_inspector.cc:26
26      return REJECTED;

As you see above, while I put a break on line 19, gdb doesn't stop on that line and skip it to line 26, why?

When I replace 0xC802 with 0xC8020000 in line 19, then it works fine the gdb doesn't miss line 19 anymore:

 //l2tp_inspector.cc
 14   else if (f_info->key.proto == UDP_PROTO) {
 15     if (size >= 4) {
 16       uint32_t l2tp_part;
 17       l2tp_part = *((uint32_t*)(data));
 18 
 19       if ((l2tp_part & 0xFFFF0000) == 0xC8020000 &&                                                                                                                  
 20           (l2tp_part & 0x0000FFFF) == size) {
 21         f_info->protocol_id = Bina::Protocols::UDP_L2TP;
 22         f_info->application_id = Bina::Applications::UNKNOWN;
 23         return PROTOCOL_ACCEPTED_FINALIZED;
 24       }
 25     }
 26     return REJECTED;
 27   }

gdp output:

test@ubuntu:~/prj$ gdb prj-loader 
GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git
This GDB was configured as "x86_64-linux-gnu".

(gdb) b l2tp_inspector.cc:17
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (l2tp_inspector.cc:17) pending.

(gdb) b l2tp_inspector.cc:18
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (l2tp_inspector.cc:18) pending.

(gdb) b l2tp_inspector.cc:19
No source file named l2tp_inspector.cc.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 3 (l2tp_inspector.cc:19) pending.

(gdb) r
Starting program: ~/prj/prj-loader 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[2017-02-02 08:53:07.201600] [0x00007ffff7fc9780] [info]    New id registered TCP with id 0
[2017-02-02 08:53:07.201677] [0x00007ffff7fc9780] [info]    New id registered TCP_PAYLOAD with id 1
[2017-02-02 08:53:07.201711] [0x00007ffff7fc9780] [info]    New id registered UDP with id 2
[2017-02-02 08:53:07.201728] [0x00007ffff7fc9780] [info]    New id registered UDP_PAYLOAD with id 3
[2017-02-02 08:53:07.201757] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:53:07.201773] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:53:07.201817] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:53:07.201832] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:53:07.201853] [0x00007ffff7fc9780] [info]    New id registered IPV4 with id 4
[2017-02-02 08:53:07.201871] [0x00007ffff7fc9780] [info]    New id registered IPV4FRAG with id 5
[2017-02-02 08:53:07.201888] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:53:07.201903] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:53:07.201933] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:53:07.201951] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:53:07.201968] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:53:07.201983] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:53:07.201998] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:53:07.202023] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:53:07.202048] [0x00007ffff7fc9780] [info]    Already registered id TCP with id 0
[2017-02-02 08:53:07.202067] [0x00007ffff7fc9780] [info]    Already registered id TCP_PAYLOAD with id 1
[2017-02-02 08:53:07.202083] [0x00007ffff7fc9780] [info]    Already registered id UDP with id 2
[2017-02-02 08:53:07.202099] [0x00007ffff7fc9780] [info]    Already registered id UDP_PAYLOAD with id 3
[2017-02-02 08:53:07.202114] [0x00007ffff7fc9780] [info]    Already registered id IPV4 with id 4
[2017-02-02 08:53:07.202133] [0x00007ffff7fc9780] [info]    Already registered id IPV4FRAG with id 5
[2017-02-02 08:53:07.202150] [0x00007ffff7fc9780] [info]    New id registered ETHERNET with id 6

Breakpoint 1, inspect (f_info=0x7fffffffce50, data=0x555555be439a "\310\002", size=106, s_module=@0x7fffffffcde0: 0x0)
    at ../src/modules/prj-lib/src/proto-inspectors/l2tp_inspector.cc:17
17        l2tp_part = *((uint32_t*)(data));

(gdb) s
Breakpoint 2, inspect (f_info=0x7fffffffce50, data=0x555555be439a "\310\002", size=106, s_module=@0x7fffffffcde0: 0x0)
    at ../src/modules/prj-lib/src/proto-inspectors/l2tp_inspector.cc:19
19        if ((l2tp_part & 0xFFFF0000) == 0xC8020000 && 

(gdb) s
26      return REJECTED;

Why dbg skipped line 19 in first snippet but it stop on it in second snippet? Almost everything is the same and the only difference is that value.

Ebrahim Ghasemi
  • 5,850
  • 10
  • 52
  • 113

2 Answers2

3

I guess I got the point.

Short answer:

Compiler Optimization remove the if condition with its block entirely!

Long Answer:

The result of (l2tp_part & 0xFFFF0000) == 0xC802 in the if condition is always false! Because we are comparing a 4-bytes number that has 2-least significant bytes equal to 0x0000, with a 2-bytes non-zero number. In the other words we compare 0xXXXX0000 with 0x0000C802 and obviously they are not equal in any case. So the whole the condition is false always and as the if block is redundant, the compiler remove it. So debugger can't stop on that line.

Ebrahim Ghasemi
  • 5,850
  • 10
  • 52
  • 113
0

If info break correctly shows your break point you set, but gdb doesn't stop on it when you type run or r, it means that line of code has been optimized out!

To solve the problem, compile your code with the -O0 -ggdb flags to ensure optimization is OFF and the debug symbols are turned ON and optimized for gdb.

Example build and run command to run it in gdb:

# download the file "type_punning.c"
wget https://raw.githubusercontent.com/Generalsimus/eRCaGuy_hello_world/master/c/type_punning.c

# build it with optimization OFF (`-O0`) and debugging symbols ON (`-ggdb`), 
# and output all intermediary files (`-save-temps=obj`), and run it in the 
# gdb debugger (`gdb bin/type_punning`)
mkdir -p bin && gcc -Wall -Wextra -Werror -O0 -ggdb -std=c11 -save-temps=obj \
type_punning.c -o bin/type_punning && gdb bin/type_punning

Now, with gdb running, set a breakpoint in "type_punning.c" on line 52, and run to that point:

# set breakpoint
b type_punning.c:52
# run to that point
r

References and additional study

  1. @Ebrahim Ghasemi's answer, where he mentions the line was optimized out!
  2. [my Q&A] What's the difference between a compiler's `-O0` option and `-Og` option?
  3. [my Q&A] https://askubuntu.com/questions/1349047/where-do-i-find-core-dump-files-and-how-do-i-view-and-analyze-the-backtrace-st
  4. [my ans. & full demo; cross-linked] gdb: show typeinfo of some data
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265