$ gdb -v GNU gdb (GDB) 9.0.50.20191210-git Copyright (C) 2019 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. $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release --enable-default-pie --enable-default-ssp --enable-cet=auto gdc_include_dir=/usr/include/dlang/gdc Thread model: posix gcc version 9.2.0 (GCC) $ cat small.c const signed char NM[] = {-1, 0, 1}; __attribute__((noinline)) void f(short delta) { short p = 2, s; for (s = 0; s < 2; s++) { p += delta; if (NM[p] == 0) asm volatile(""); } } void main(void) { f(-1); } $ gcc -g small.c $ gdb -q ./a.out Reading symbols from ./a.out... (gdb) break small.c:9 Breakpoint 1 at 0x113f: file small.c, line 9. (gdb) run Starting program: /home/yibiao/cv-gcov/a.out Breakpoint 1, f (delta=-1) at small.c:9 9 if (NM[p] == 0) (gdb) step 10 asm volatile(""); (gdb) c Continuing. Breakpoint 1, f (delta=-1) at small.c:9 9 if (NM[p] == 0) (gdb) step 10 asm volatile(""); (gdb) q A debugging session is active. Inferior 1 [process 4947] will be killed. Quit anyway? (y or n) y ############################################################################### ### We can find that Line #10 @asm volatile("");@ is executed twice. ### However, it is obvious that Line #9 "if (NM[p] == 0)" is True in the second for loop. ###############################################################################
In current version of GDB, statement with asm volatile will be skipped. I was wondering that this is the default behavior of GDB. Therefore, I think this bug in previous version is a bug of GDB.
(In reply to Yibiao Yang from comment #1) > In current version of GDB, statement with asm volatile will be skipped. > > I was wondering that this is the default behavior of GDB. > Compiling with gcc 9.3.1, and looking at the line info using readline -wL, I get: ... CU: small.c: Line number Starting address View Stmt 4 0x400492 x 5 0x40049c x 6 0x4004a2 x 6 0x4004a8 x 8 0x4004aa x 9 0x4004b8 x 9 0x4004c5 x 10 0x4004c9 x 6 0x4004c9 1 x 6 0x4004d4 x 12 0x4004db x 14 0x4004df x 14 0x4004e3 x 14 0x4004ed x 14 0x4004f0 x ... while we have: ... $ cat -n small.c 1 const signed char NM[] = {-1, 0, 1}; 2 3 __attribute__((noinline)) void f(short delta) 4 { 5 short p = 2, s; 6 for (s = 0; s < 2; s++) 7 { 8 p += delta; 9 if (NM[p] == 0) 10 asm volatile(""); 11 } 12 } 13 14 void main(void) { f(-1); } 15 ... So, the line with the asm stmt does have line info, but shares the address with another entry with another line number. Using this debugging session, we can see that we do visit the address, but show line 6 instead of line 10: ... (gdb) 9 if (NM[p] == 0) (gdb) p /x $pc $1 = 0x4004b8 (gdb) s 6 for (s = 0; s < 2; s++) (gdb) p /x $pc $2 = 0x4004c9 (gdb) ... which I'd say is a valid interpretation of the line number info.
(In reply to Yibiao Yang from comment #0) > $ gdb -q ./a.out > Reading symbols from ./a.out... > (gdb) break small.c:9 > Breakpoint 1 at 0x113f: file small.c, line 9. > (gdb) run > Starting program: /home/yibiao/cv-gcov/a.out > > Breakpoint 1, f (delta=-1) at small.c:9 > 9 if (NM[p] == 0) > (gdb) step > 10 asm volatile(""); > (gdb) c > Continuing. > > Breakpoint 1, f (delta=-1) at small.c:9 > 9 if (NM[p] == 0) > (gdb) step > 10 asm volatile(""); > (gdb) q > A debugging session is active. > > Inferior 1 [process 4947] will be killed. > > Quit anyway? (y or n) y > > > > ############################################################################# > ## > ### We can find that Line #10 @asm volatile("");@ is executed twice. > ### However, it is obvious that Line #9 "if (NM[p] == 0)" is True in the > second for loop. > ############################################################################# > ## I think this is a different variant of the same problem: the target of the true _and_ false path end up at the same insn, which has two entries in the line table. So either we show the "true" line twice, or the "false" line twice. Confusing, but not a gdb bug. On the gcc side, it could be argued that this is exactly what you asked for by providing an _empty_ asm stmt.