2

I would like to create a backtrace in gdb (in a script). The command bt 2 prints only the 2 innermost frames, while bt -2 prints only the 2 outermost frames.

What I'd like to do is to skip the 2 innermost frames, and show all outer frames. I've tried

up 2
bt

(and similarly up-silently, frame, select-frame), but it doesn't affect the output of bt. To be clear, I want to get rid of the first to lines in this output:

#0  0x0000003167e0f33e in waitpid () from /lib64/libpthread.so.0
#1  0x00007f2779835de8 in print_trace() () at /path/to/MyAnalysis.cxx:385
#2  0x00007f2779836ec9 in MyAnalysis::getHistHolder(std::basic_string<char, std::char_traits<char>, std::allocator<char> >) () at /path/to/MyAnalysis.cxx:409
#3  0x00007f27798374aa in MyAnalysis::execute() () at /path/to/MyAnalysis.cxx:599
#4  0x00007f2783a9670f in EL::Worker::algsExecute() () from /blah/lib/libEventLoop.so
...

Any way to do this?

Calling return twice seems to work, but then the application is left in an invalid state afterwards, so I can't use it.

jdm
  • 8,842
  • 9
  • 49
  • 100
  • 1
    Would the downvoters care to explain what is wrong with this question? – jdm Dec 06 '16 at 09:40
  • would writing your own filter be an option? https://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Frame-Filter.html – Marcus Müller Dec 06 '16 at 09:45
  • @MarcusMüller Thanks for the link. That would be an option, but it is probably overkill for such a cosmetic issue. (Also, I'm currently disabling python script auto-loading when I call gdb, so it would need a bit of work.) I'm really surprized there seems to be no simple way to set the current frame. – jdm Dec 06 '16 at 10:03
  • I first thought of something like "finding the frame number of the `main` function, then subtract two of that, and do a `bt -result`", but that would just be more complicated than filtering – Marcus Müller Dec 06 '16 at 10:05
  • 1
    For context, I'm using [this dirty trick](http://stackoverflow.com/a/4732119/143091) to have my program invoke gdb on itself to print a stackflow (the result is more readable than anything you can get easily by `backtrace()`). – jdm Dec 06 '16 at 11:26
  • You can `finish` twice instead of `return` twice. – ks1322 Dec 06 '16 at 15:20

1 Answers1

0

Your argument to "bt" depends on current number of frames present. Probably this can also be done in gdb directly (not sure), but this python script does exactly this:

import gdb

class TopBt (gdb.Command):
    """ tbt n Shows backtrace for top n frames """

    def __init__ (self):
        super(TopBt, self).__init__ ("tbt", gdb.COMMAND_DATA)

    def framecount():
        n = 0
        f = gdb.newest_frame()
        while f:
            n = n + 1
            f = f.older()
        return n

    def invoke (self, arg, from_tty):
        top = int(arg[0])
        btarg = -(TopBt.framecount() - top)
        if btarg < 0:
            gdb.execute("bt  " + str(btarg))
TopBt()

Save this to some file (tbt.py), source it in gdb (source tbt.py). Now you have new command tbt. tbt N will print backtrace for all but top N frames.

dbrank0
  • 8,606
  • 2
  • 39
  • 55