Created attachment 14825 [details] triggering source code of small.c $ cat small.c -n 1 volatile int v; 2 3 int 4 foo (char *p) 5 { 6 char *p2 = p + 20; 7 v = p > p2; 8 return v; 9 } 10 11 int 12 main () 13 { 14 char *p = (char *)__builtin_malloc (42); 15 int r = foo (p); 16 __builtin_free (p); 17 18 return 0; 19 } $ gcc -O1 -g small.c $ gdb -q a.out Reading symbols from a.out... (gdb) start Temporary breakpoint 1 at 0x401117: file small.c, line 7. Starting program: /root/devil/batch/a.out Temporary breakpoint 1, main () at small.c:15 15 int r = foo (p); (gdb) s foo (p=<optimized out>) at small.c:7 7 v = p > p2; (gdb) s 8 return v; (gdb) s main () at small.c:18 18 return 0; (gdb) $ gdb -q a.out Reading symbols from a.out... (gdb) start Temporary breakpoint 1 at 0x401117: file small.c, line 7. Starting program: /root/devil/batch/a.out Temporary breakpoint 1, main () at small.c:15 15 int r = foo (p); (gdb) si foo (p=<optimized out>) at small.c:8 8 return v; (gdb) si main () at small.c:18 18 return 0; (gdb) si 0x000000000040112c 18 return 0; (gdb) /**************** we can found that line 7 is reached in source-level stepping. However, it cannot be reached at instruction-level stepping. I was wondering that this inconsistent behavior might misleading the users. ****************/ $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/13.0.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: ../gcc-git/configure --enable-languages=c,c++ --disable-multilib Thread model: posix Supported LTO compression algorithms: zlib gcc version 13.0.0 20221107 (experimental) (GCC) $ gdb -v GNU gdb (GDB) 13.0.50.20221107-git Copyright (C) 2022 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.
(In reply to Yibiao Yang from comment #0) > we can found that line 7 is reached in source-level stepping. However, it > cannot be reached at instruction-level stepping. I was wondering that this > inconsistent behavior might misleading the users. It's because of ( https://sourceware.org/gdb/onlinedocs/gdb/Inline-Functions.html#Inline-Functions ): ... The body of an inlined function is directly included at its call site; unlike a non-inlined function, there are no instructions devoted to the call. GDB still pretends that the call site and the start of the inlined function are different instructions. Stepping to the call site shows the call site, and then stepping again shows the first line of the inlined function, even though no additional instructions are executed. This makes source-level debugging much clearer; you can see both the context of the call and then the effect of the call. Only stepping by a single instruction using stepi or nexti does not do this; single instruction steps always show the inlined body. ... If after reading this you still think it's misleading, you can file an enhancement PR to let users turn off this feature. For now, resolving as not-a-bug.
(In reply to Tom de Vries from comment #1) > If after reading this you still think it's misleading, you can file an > enhancement PR to let users turn off this feature. Also, you can look into "set print frame-info " ( https://sourceware.org/gdb/onlinedocs/gdb/Print-Settings.html#index-set-print-frame_002dinfo ). For instance, location-and-address makes it more clear when this behavior is happening: the line number changes but the pc stays the same. Alternatively, you could consider using TUI, with a asm/src layout: ... (gdb) tui new-layout src-asm src 1 asm 1 status 0 cmd 1 (gdb) layout src-asm ... You can see both the current instruction, and the current line, so it's easy to see when you're executing an insn in main but the line is in foo.
(In reply to Tom de Vries from comment #2) > Alternatively, you could consider using TUI, with a asm/src layout: > ... > (gdb) tui new-layout src-asm src 1 asm 1 status 0 cmd 1 > (gdb) layout src-asm > ... > > You can see both the current instruction, and the current line, so it's easy > to see when you're executing an insn in main but the line is in foo. Like so: ... ┌─test.c─────────────────────────────────────────────────────────────────────┐ │ > 7 v = p > p2; │ │ 8 return v; │ │ 9 } │ │ 10 │ ┌────────────────────────────────────────────────────────────────────────────┐ │ >0x4004a7 <main> movl $0x0,0x1b73(%rip) # 0x402024 <v> │ │ 0x4004b1 <main+10> mov 0x1b6d(%rip),%eax # 0x402024 <v> │ │ 0x4004b7 <main+16> mov $0x0,%eax │ └────────────────────────────────────────────────────────────────────────────┘ native process 5771 In: main L7 PC: 0x4004a7 (gdb) ...
(In reply to Tom de Vries from comment #2) > (In reply to Tom de Vries from comment #1) > > If after reading this you still think it's misleading, you can file an > > enhancement PR to let users turn off this feature. > > Also, you can look into "set print frame-info " ( > https://sourceware.org/gdb/onlinedocs/gdb/Print-Settings.html#index-set- > print-frame_002dinfo ). > > For instance, location-and-address makes it more clear when this behavior is > happening: the line number changes but the pc stays the same. > > Alternatively, you could consider using TUI, with a asm/src layout: > ... > (gdb) tui new-layout src-asm src 1 asm 1 status 0 cmd 1 > (gdb) layout src-asm > ... > > You can see both the current instruction, and the current line, so it's easy > to see when you're executing an insn in main but the line is in foo. Thank you very much for the detailed explanation. Yes, I can found that the instruction is not changed when using source-level stepping for this inlined function. After reading GDB's default behavior for inlined function you mentioned, I understand why debugger has such a behavior. However, I was wondering the GCC side could do better for inlined functions by establishing a mapping between the inserted copy function body with the orginal function code when the '-g' flag is enabled. In this way, gdb can display which source code the instruction belongs to when stepping at instruction level.
(In reply to Yibiao Yang from comment #4) > Thank you very much for the detailed explanation. Yes, I can found that the > instruction is not changed when using source-level stepping for this inlined > function. After reading GDB's default behavior for inlined function you > mentioned, I understand why debugger has such a behavior. Ack. > However, I was > wondering the GCC side could do better for inlined functions by establishing > a mapping between the inserted copy function body with the orginal function > code when the '-g' flag is enabled. Well, that information is there in the form of DW_TAG_inlined_subroutine, which is why you're seeing what you're seeing when stepping. > In this way, gdb can display which > source code the instruction belongs to when stepping at instruction level. Well, AFAIU, gdb does exactly that, using the line info.