Bug 32011 - gdb has reached a line that the program has never reached.
Summary: gdb has reached a line that the program has never reached.
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 13.1
: P2 enhancement
Target Milestone: 16.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 32010 (view as bug list)
Depends on:
Blocks:
 
Reported: 2024-07-23 07:27 UTC by Hu ZW
Modified: 2024-08-08 10:11 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2024-07-31 00:00:00


Attachments
The source file (76.48 KB, application/x-zip-compressed)
2024-07-23 07:29 UTC, Hu ZW
Details
Preprocessed program. (33.33 KB, application/x-zip-compressed)
2024-08-01 13:08 UTC, Hu ZW
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Hu ZW 2024-07-23 07:27:20 UTC
This program was generated by csmith and compiled at -O1. While single-stepping, a line was reached that the program had not yet executed.
gcc version:9.4.0 (installed by sudo command)
gdb version:13.2
os:Ubuntu 20.04


The problem occurs on line 333.The problem occurs on line 333. This line is not a return statement in the source code.

Reading symbols from ./random_64.o...
(gdb) b func_1
Breakpoint 1 at 0x31f4: file random_64_mutated.c, line 224.
(gdb) r
Starting program: /home/hzw/experiment/mutation/mutated_files/random_64.o 

Breakpoint 1, func_1 () at random_64_mutated.c:224
224	    int32_t l_2166 = 1L;
(gdb) n
247	    g_2153[0] = func_2((func_4(func_7(g_11, l_12, g_11), (l_12 < l_12)) , ((safe_mul_func_uint8_t_u_u(0xDCL, (l_1915 = ((func_4(((*l_1908)--), l_12) , g_1630.f1) | 0UL)))) >= 6L)));
(gdb) 
248	int32_t c_61 = l_1915 * l_2166;
(gdb) 
250	int32_t c_63 = l_2166 * (*(*l_2366));
(gdb) 
256	int32_t c_69 = l_1915 * l_1915;
(gdb) 
278	g_2476[2][3][0] = c_89 - c_90;
(gdb) 
279	    if ((~(safe_div_func_uint8_t_u_u(((((254UL && (((safe_rshift_func_uint16_t_u_s((((safe_mul_func_uint32_t_u_u((safe_sub_func_int64_t_s_s((safe_rshift_func_uint64_t_u_u(((l_2166 |= (0x60DEL | (l_1915 = l_12))) , (l_2167 != l_2165[0])), 40)), (l_12 <= (safe_rshift_func_int8_t_s_s(l_12, ((*l_2170) = (((l_12 , l_1908) != l_1908) <= g_841.f0))))))), l_12)) | g_1399) , 0x5B0BL), l_12)) <= l_12) >= 0xEC13E069L)) ^ g_388) != 0x74L) , g_120.f1), l_12))))
(gdb) 
288	        (*g_105) = (safe_mod_func_int32_t_s_s((l_12 == ((safe_rshift_func_uint64_t_u_u((l_2175[0] == ((l_2176 == l_2176) , (((&g_579 != l_2177) , l_2178) , (((*g_657) , (255UL ^ 0xE6L)) , (*g_1254))))), 45)) & l_1915)), 4294967291UL));
(gdb) 
333	  return 
(gdb) 
289	        (*g_2180) = (*g_1305);
(gdb) 
321	g_1388[0][0][3] = c_119 + c_120;
(gdb) 
740	    (*l_2366) = l_2532[0];
(gdb) 
main (argc=<optimized out>, argv=<optimized out>) at random_64_mutated.c:1760
1760	    csmith_sink_ = g_11;


After that, I tried to execute it with lldb in single step. After executing the if statement, lldb went back to execute the statement of the previous basic block. It seems that some kind of optimization scheduled the instructions, causing gdb to have an error.

I attached the debugging information printed by llvm-dwarfdump, I hope it helps.
Comment 1 Hu ZW 2024-07-23 07:29:05 UTC
Created attachment 15639 [details]
The source file
Comment 2 Hu ZW 2024-07-23 07:36:39 UTC
I'm so sorry, I made a mistake and submitted twice. I didn't understand how to delete the previous submission.
Comment 3 Hannes Domani 2024-07-23 14:53:43 UTC
*** Bug 32010 has been marked as a duplicate of this bug. ***
Comment 4 Tom de Vries 2024-07-31 08:30:06 UTC
In this comment (PR32010 comment 1) in the duplicate we find this question:
...
When you are on this line, can you try to find out where it is from?
Because I don't think gdb just invented it.

You can try any or all of these commands:
frame
bt
info source
...

I found that information in the zip file:
...
Address            Line   Column File   ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
  ...
0x0000000000003452    288      9      1   0             0  is_stmt
0x0000000000003452    288    160      1   0             0
0x000000000000345b    288    190      1   0             0
0x0000000000003462    288     10      1   0             0
0x0000000000003469    288     10      1   0             0
0x0000000000003469    333      3      2   0             0  is_stmt
0x0000000000003469    288     18      1   0             0
0x000000000000346f    289      9      1   0             0  is_stmt
0x000000000000346f    289     22      1   0             0
0x0000000000003476    289     10      1   0             0
0x000000000000347d    289     22      1   0             0
0x0000000000003480    289     19      1   0             0
...

So, line 288 is from file 1:
...
file_names[  1]:
           name: "random_64_mutated.c"
...

And line 333 is from file 2:
...
file_names[  2]:
           name: "safe_math.h"
...

The thing that is confusing is that gdb doesn't mention that it's going to a line in a different file.

But that may be due to a user setting "set print frame-info source-line".
Comment 5 Tom de Vries 2024-07-31 08:43:50 UTC
Can you do:
...
(gdb) show print frame-info 
...
to see what the value is when you run into this problem?

If this is not due to a non-standard setting of "print frame-info", the submitted info is not sufficient to reproduce the problem:
...
$ gcc random_64_mutated.c -g -O1
random_64_mutated.c:10:10: fatal error: csmith.h: No such file or directory
 #include "csmith.h"
          ^~~~~~~~~~
compilation terminated.
...

Can you post a compilable test-case?  For instance, a preprocessed file might be sufficient.
Comment 6 Hu ZW 2024-08-01 13:08:36 UTC
Created attachment 15657 [details]
Preprocessed program.
Comment 7 Hu ZW 2024-08-01 13:20:33 UTC
Sorry for forgetting to deal with the csmith header file. The gdb command shows "Printing of frame information is 'auto'".The problem is that when single-step debugging reaches line 333, gdb displays a return statement, but line 333 in the source code is not a return statement.So I guess this may be a bug.
333   int32_t *l_2235 = &g_15[0][0][0];
Comment 8 Tom de Vries 2024-08-01 20:34:21 UTC
(In reply to Hu ZW from comment #7)
> Sorry for forgetting to deal with the csmith header file. The gdb command
> shows "Printing of frame information is 'auto'".The problem is that when
> single-step debugging reaches line 333, gdb displays a return statement, but
> line 333 in the source code is not a return statement.So I guess this may be
> a bug.
> 333   int32_t *l_2235 = &g_15[0][0][0];

I get:
...
(gdb) n
288	in random_64_mutated.c
(gdb) n
warning: 333	/home/hzw/experiment/csmith/install/include/safe_math.h: No such file or directory
(gdb) n
warning: 289	random_64_mutated.c: No such file or directory
(gdb) 
...

So line 333 is indeed as previously stated in comment 4, not in random_64_mutated.c.

Looking in the preprocessed file, we have:
...
# 322 "/home/hzw/experiment/csmith/install/include/safe_math.h"
                                                                                                                     \
                                                                                                                     \
    / si1)))) ?
    ((si1)) :


    si1 * si2;
}

static int32_t
(safe_mod_func_int32_t_s_s)(int32_t si1, int32_t si2 )
{

  return

    ((si2 == 0) || ((si1 ==
# 335 "/home/hzw/experiment/csmith/install/include/safe_math.h" 3 4
...
which clearly shows the return at line 333 of safe_math.h.
Comment 9 Tom de Vries 2024-08-01 20:51:10 UTC
What does surprise me is that the change of file is not shown.

That's easily reproducible with:
...
$ cat test.c
int var;

int
foo (void)
{
  var = 1;
#include "test.h"
}

int
main ()
{
  return foo ();
}
$ cat test.h
  return 1;
$ gcc test.c -g
$ gdb -q a.out -ex start
Reading symbols from a.out...
Temporary breakpoint 1 at 0x4004b0: file test.c, line 13.
Starting program: /data/vries/gdb/a.out 

Temporary breakpoint 1, main () at test.c:13
13	  return foo ();
(gdb) step
foo () at test.c:6
6	  var = 1;
(gdb) n
1	  return 1;
(gdb) 
8	}
(gdb) 
...

In contrast, with "set print frame-info source-and-location" we have:
...
(gdb) step
foo () at test.c:6
6	  var = 1;
(gdb) n
foo () at test.h:1
1	  return 1;
(gdb) 
foo () at test.c:8
8	}
(gdb) 
...

So, maybe the "auto" behaviour that "will switch between source-line and source-and-location depending on the program counter" needs an update.
Comment 10 Tom de Vries 2024-08-02 03:20:32 UTC
Using:
...
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 06b454bf78f..82132fb589d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -9296,12 +9296,23 @@ print_stop_location (const target_waitstatus &ws)
 	  && (tp->control.step_start_function
 	      == find_pc_function (tp->stop_pc ())))
 	{
-	  /* Finished step, just print source line.  */
-	  source_flag = SRC_LINE;
+	  symtab_and_line sal = find_frame_sal (get_selected_frame (nullptr));
+	  if (sal.symtab != tp->current_symtab)
+	    {
+	      /* Finished step in same frame but into different file, print
+		 location and source line.  */
+	      source_flag = SRC_AND_LOC;
+	    }
+	  else
+	    {
+	      /* Finished step in same frame and same file, just print source
+		 line.  */
+	      source_flag = SRC_LINE;
+	    }
 	}
       else
 	{
-	  /* Print location and source line.  */
+	  /* Finished step into different frame, print location and source line.  */
 	  source_flag = SRC_AND_LOC;
 	}
       break;
...
I get:
...
(gdb) s
foo () at test.c:6
6	  var = 1;
(gdb) n
foo () at test.h:1
1	  return 1;
(gdb) n
foo () at test.c:8
8	}
(gdb) 
...
Comment 12 Sourceware Commits 2024-08-05 12:00:36 UTC
The master branch has been updated by Tom de Vries <vries@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b464e193d116bd752375b92cc65c676cbd6f00fa

commit b464e193d116bd752375b92cc65c676cbd6f00fa
Author: Tom de Vries <tdevries@suse.de>
Date:   Mon Aug 5 14:00:42 2024 +0200

    [gdb] Notice when stepping into different file
    
    Consider the following test-case:
    ...
    $ cat -n test.c
         1  int var;
         2
         3  int
         4  foo (void)
         5  {
         6    var = 1;
         7  #include "test.h"
         8  }
         9
        10  int
        11  main ()
        12  {
        13    return foo ();
        14  }
    $ cat -n test.h
         1    return 1;
    $ gcc test.c -g
    ...
    
    When stepping through the test-case, gdb doesn't make it explicit that line 1
    is not in test.c:
    ...
    Temporary breakpoint 1, main () at test.c:13
    13        return foo ();
    (gdb) step
    foo () at test.c:6
    6         var = 1;
    (gdb) n
    1         return 1;
    (gdb)
    8       }
    (gdb)
    ...
    which makes it easy to misinterpret the output.
    
    This is with the default "print frame-info" == auto, with documented
    behaviour [1]:
    ...
    stepi will switch between source-line and source-and-location depending on the
    program counter.
    ...
    
    What is actually implemented is that source-line is used unless stepping into
    or out of a function.
    
    The problem can be worked around by using
    "set print frame-info source-and-location", but that's a bit verbose.
    
    Instead, change the behaviour of "print frame-info" == auto to also use
    source-and-location when stepping into another file, which gets us:
    ...
    (gdb) n
    foo () at test.h:1
    1         return 1;
    ...
    
    Tested on x86_64-linux.
    
    Reviewed-By: Kevin Buettner <kevinb@redhat.com>
    Reviewed-By: Kévin Le Gouguec <legouguec@adacore.com>
    
    PR gdb/32011
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32011
    
    [1] https://sourceware.org/gdb/current/onlinedocs/gdb.html/Print-Settings.html#index-set-print-frame_002dinfo
Comment 13 Tom de Vries 2024-08-05 12:01:37 UTC
Enhancement committed.