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
  • 9,470
  • 12
  • 58
  • 110
  • 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

2 Answers2

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
  • 9,026
  • 2
  • 37
  • 55
0

If it's ok for the stack to be capped at some pre-determined length, you can provide an explicit long list, like this for up to 40 frames starting at frame 4:

frame apply level 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 43 -q frame

Frame numbers beyond what's available appear to be ignored.

Peter Dillinger
  • 2,757
  • 2
  • 14
  • 7