public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* preserving arguments through the parent-child exec chain and keeping history
@ 2016-05-16 18:21 Daniel Gutson
  0 siblings, 0 replies; only message in thread
From: Daniel Gutson @ 2016-05-16 18:21 UTC (permalink / raw)
  To: gdb, Martin Galvan

[-- Attachment #1: Type: text/plain, Size: 2788 bytes --]

Consider these facts in a scenario of an exec chain with set
follow-fork-mode child, for example gcc -> cc1plus:

 * after the last inferior finishes, gdb "remains" (remembers) in the
last exec, so issueing "run" runs the latest.
 * the arguments passed to the main() of the last exec are lost, so
"show args" shows ""
 * the very initial arguments passed to gdb with set args or --args
used for the first program are also lost
 * there is no way to "back trace" the history of executed programs,
of course not knowing their arguments; only the last program is
preserved.

To do a proof of concept, the attached py script keeps tracks of the
arguments passed to main() and set args accordingly, so
in the example of gcc calling cc1plus now we can repeatedly run
cc1plus with the arguments that gcc passed.

However, I would like to discuss a more general and better solution:
the ability to keep track of all executed
binaries with their arguments, and to be able to "navigate" through
that list once all the inferiors finished, so we can
re-run starting at any point in the history of chained execs with the
same arguments it was called before. This list
would be re-populated per-run basis.

Despite I think we could develop this enhancement as a python script,
do you people think that, in case of interest
in the general idea, implementing this as a core feature would be better?

For example, given the command line
    gdb --args ~/bin/gcc61/bin/g++61 -Wall -Wextra -Wpedantic
-std=c++14 -ggdb3 shuffle.cpp
and issueing
   (gdb) set follow-fork-mode child
   (gdb) run

Then, after everything finishes, I propose something like this:

(gdb) info execs
  Id    Path
                                                 args
  1     ../../../gcc-6.1.0/gcc/gcc-main.c
                                     -Wall -Wextra -Wpedantic
-std=c++14 -ggdb3 shuffle.cpp
  2     /home/dgutson/bin/gcc61/libexec/gcc/x86_64-pc-linux-gnu/6.1.0/cc1plus
 -quiet -imultiarch x86_64-linux-gnu -dD -D_GNU_SOURCE shuffle.cpp
-quiet -dumpbase shuffle.cpp -mtune=generic -march=x86-64 -auxbase
shuffle -ggdb3 -Wall -Wextra -Wpedantic -std=c++14 -o /tmp/ccuquQNR.s

(gdb) exec 2


The first command (info execs) shows what programs where exec'd after
a full run (assuming follow-fork-mode child).
The second command re-runs starting from cc1plus with the arguments
that gcc passed to cc1plus. Similarly,
issueing "exec 1" re-runs everything again.

Feedback?

Thanks,

   Daniel.

ps: sorry for exceeding the 79-cols limit

-- 

Daniel F. Gutson
Engineering Manager

San Lorenzo 47, 3rd Floor, Office 5
Córdoba, Argentina

Phone:   +54 351 4217888 / +54 351 4218211
Skype:    dgutson
LinkedIn: http://ar.linkedin.com/in/danielgutson

[-- Attachment #2: preserve_args.py --]
[-- Type: text/x-python, Size: 1457 bytes --]

# Copyright (C) Martin Galvan 2016, martin.galvan@tallertechnologies.com
import gdb

class MainBreakpoint(gdb.Breakpoint):
    def stop(self):
        frame = gdb.selected_frame()
        block = frame.block()
        args = []

        # Go upwards until we find the block representing the function.
        # We probably don't need to check if we arrived to the static block,
        # but it shouldn't hurt.
        while not block.function and not block.is_static:
            block = block.superblock

        if block.function:
            args = [symbol.value(frame) for symbol in block if symbol.is_argument]

        if args:
            argc = int(args[0])
            argv = args[1]

            # argv is a gdb.Value representing an array. We can access the array
            # elements using the [] operator.
            # Don't grab the program name since gdb automatically sets it as an
            # arg, even if 'show args' doesn't show it.
            args = [argv[i].string() for i in range(1, argc)]

        args = ' '.join(args)
        gdb.execute('set args {0}'.format(args))

        return True

#gdb.execute('set follow-fork-mode child')
MainBreakpoint('main')

# Run to a's main.
#gdb.execute('run')

# Run to b's main.
#gdb.execute('continue')
#gdb.execute('show args')

# Re-run b.
#gdb.execute('run')
#gdb.execute('show args')
#gdb.execute('continue')

# b should show us the same arguments we used when execv'ing it from a.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2016-05-16 18:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-16 18:21 preserving arguments through the parent-child exec chain and keeping history Daniel Gutson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).