Bug 25528 - step will stopped at any "asm volatile" statement
Summary: step will stopped at any "asm volatile" statement
Status: RESOLVED NOTABUG
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 critical
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-02-10 16:18 UTC by Anonymous
Modified: 2020-12-30 17:16 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anonymous 2020-02-10 16:18:40 UTC
$ 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. 
###############################################################################
Comment 1 Anonymous 2020-12-29 03:33:51 UTC
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.
Comment 2 Tom de Vries 2020-12-30 17:02:58 UTC
(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.
Comment 3 Tom de Vries 2020-12-30 17:16:13 UTC
(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.