Greg Nisbet
Greg Nisbet

Reputation: 6994

gdb step until source is available again

I'm running GNU grep under gdb on linux and single stepping it. After about 12 steps, control is transferred to setlocale.c, for which no source code is available.

Example session, after step 12 no source code information is available and the list command just shows the file.

Is there a way of getting gdb to keep stepping until a file with source code is available again. Alternatively, is there a way of telling gdb to keep stepping until control is transferred to a different file?

example session, showing source code initially available and then unavaiable for setlocale.c?

(gdb) start
Temporary breakpoint 1 at 0x402e50: file grep.c, line 2415.
Starting program: ~/ws/opt/grep/out/bin/grep --context=20 -r --line-number --byte-offset --include=\*.c int .
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Temporary breakpoint 1, main (argc=0x8, argv=0x7fffffffdaa8) at grep.c:2415
2415    {
(gdb) l
2410      return result;
2411    }
2412    
2413    int
2414    main (int argc, char **argv)
2415    {
2416      char *keys = NULL;
2417      size_t keycc = 0, oldcc, keyalloc = 0;
2418      int matcher = -1;
2419      bool with_filenames = false;
(gdb) s 12
__GI_setlocale (category=category@entry=0x6, locale=locale@entry=0x420b7b "") at setlocale.c:220
220 setlocale.c: No such file or directory.
(gdb) l
215 in setlocale.c

Upvotes: 1

Views: 847

Answers (2)

Greg Nisbet
Greg Nisbet

Reputation: 6994

I ended up writing a simple gdb script using the Python API to do this. It will keep stepping until control is transfered to the next file, regardless of whether that involves adding a new stack frame or leaving the current one.

The script can be loaded with source leave_this_file.py. It defines a command called leave_this_file that can be invoked with no arguments, or given a number of times to repeat.

The script is a little bit makeshift and ends up parsing the result of the gdb command frame 0 rather than using one of gdb's proper APIs for inspecting frames.

MAX_STEPS = 10000


def get_file_name():
    """extract the file name for the bottommost frame"""
    # example string
    #0  main (argc=0x7, argv=0x7fffffffdaa8) at grep.c:2415
    # <source fragment>
    where_str = gdb.execute("frame 0", from_tty=False, to_string=True)
    # last word of first line is file:line
    file_line = where_str.splitlines()[0].split()[-1]
    filename, _, line = file_line.rpartition(":")
    # confirm that line number is an int, raise otherwise
    int(line)
    return filename


def step_out_of_file_once():
    orig_file_name = get_file_name()
    current_file_name = orig_file_name
    counter = 0
    for x in range(MAX_STEPS):
        gdb.execute("step", from_tty=False, to_string=True)
        counter += 1
        current_file_name = get_file_name()
        if orig_file_name != current_file_name:
            break
    print("%s: %30s, %s: %s" % ("new", current_file_name, "steps", counter))


class LeaveThisFile(gdb.Command):
    """step out of the current file"""

    def __init__(self):
        gdb.Command.__init__(
            self, "leave_this_file", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL, True
        )

    def invoke(self, arg, from_tty):
        # interpret the arg as a number of times to execute the command
        # 1 by default
        if arg:
            arg = int(arg)
        else:
            arg = 1
        for x in range(arg):
            step_out_of_file_once()


LeaveThisFile()

Here's some example output when running GNU grep under gdb

2415    {
(gdb) startQuit
(gdb) source leave_this_file.py 
(gdb) leave_this_file 15
new:                    setlocale.c, steps: 18
new:        pthread_rwlock_wrlock.c, steps: 8
new: ../sysdeps/unix/sysv/linux/x86/hle.h, steps: 3
new:        pthread_rwlock_wrlock.c, steps: 1
new:                    setlocale.c, steps: 7
new: ../sysdeps/x86_64/multiarch/../strcmp.S, steps: 1
new:                    setlocale.c, steps: 48
new:                       getenv.c, steps: 4
new:     ../sysdeps/x86_64/strlen.S, steps: 2
new:                       getenv.c, steps: 16
new: ../sysdeps/x86_64/multiarch/../strcmp.S, steps: 64
new:                       getenv.c, steps: 53
new:                    setlocale.c, steps: 16
new: ../sysdeps/x86_64/multiarch/../strchr.S, steps: 5
new:                    setlocale.c, steps: 23

Upvotes: 0

ks1322
ks1322

Reputation: 35815

You need gdb finish command. With this command you can go out of current stack frame which has no source code available. You can use it as many times as you want until you are again in stack frame with source code. See documentation.

Upvotes: 1

Related Questions