Ejemplo n.º 1
0
def main():
    ctx = common.parse_args()
    if ctx.input:
        threads = common.load_threads(ctx.input)
        if ctx.invert:
            common.print_inverted_callgraph(threads, ctx.threshold)
        else:
            common.print_callgraph(threads, ctx.threshold)
    elif ctx.pid:
        this_path = os.path.realpath(__file__)
        pargs = ' '.join(sys.argv[1:])

        args = [
            ctx.gdb_path, "-q", "--ex",
            "source %s" % this_path, "--ex",
            "gdbpmp %s" % pargs
        ]
        proc = subprocess.Popen(args)

        try:
            while proc.poll() is None:
                time.sleep(0.1)

        except KeyboardInterrupt:
            proc.send_signal(signal.SIGINT)
            while proc.poll() is None:
                time.sleep(0.1)
Ejemplo n.º 2
0
    def invoke(self, argument, from_tty):
        detatch_and_kill = 0
        self.dont_repeat()
        ctx = common.parse_args(gdb.string_to_argv(argument))
        if ctx.input:
            threads = common.load_threads(ctx.input)
            common.print_callgraph(threads)
            return

        gdb.execute("set print thread-events off")
        gdb.execute("set print inferior-events off")
        gdb.execute("set pagination off")

        if ctx.pid and ctx.pid != gdb.selected_inferior().pid:
            detach_and_kill = 1
            gdb.write("Attaching to process %d..." % ctx.pid)
            gdb.flush(gdb.STDOUT)
            if gdb.selected_inferior().pid != 0:
                gdb.execute("detach", to_string=True)
            os.kill(ctx.pid, signal.SIGSTOP)
            gdb.execute("attach %d" % ctx.pid, to_string=True)
            os.kill(ctx.pid, signal.SIGCONT)
            gdb.execute("continue", to_string=True)
            gdb.write("Done.\n")
            gdb.flush(gdb.STDOUT)

        def detach_attach():
            pid = gdb.selected_inferior().pid
            os.kill(pid,
                    signal.SIGSTOP)  # Make sure the process does nothing until
            # it's reattached.
            gdb.execute("detach", to_string=True)
            os.kill(pid, signal.SIGCONT)
            sleep(ctx.sleep)
            os.kill(pid, signal.SIGSTOP)
            gdb.execute("attach %d" % pid, to_string=True)
            os.kill(pid, signal.SIGCONT)
            gdb.execute("continue", to_string=True)

        def breaking_continue_handler(event):
            sleep(ctx.sleep)
            os.kill(gdb.selected_inferior().pid, signal.SIGINT)

        samples = 0
        gdb.write("Gathering Samples")
        gdb.flush(gdb.STDOUT)
        try:
            for i in range(0, ctx.samples):
                # Some processes handle signals in strange ways.  For those
                # processes we may have to fully detach from the process,
                # sleep, and then reattach.  This is quite slow.  For other
                # processes we may be able to tell gdb to continue, sleep,
                # and then send SIGINT to let GDB stop the process.
                if ctx.detachattach:
                    detach_attach()
                else:
                    gdb.events.cont.connect(breaking_continue_handler)
                    gdb.execute("continue", to_string=True)
                    gdb.events.cont.disconnect(breaking_continue_handler)
                for inf in gdb.inferiors():
                    inum = inf.num
                    for th in inf.threads():
                        thn = th.num
                        if thn not in self.threads:
                            f = GDBFunction(None, 2)
                            self.threads[thn] = GDBThread(
                                th.name, thn, th.ptid, f)
                        if ctx.match and not any(
                                m in th.name for m in ctx.match.split(',')):
                            pass
                        elif ctx.exclude and any(
                                m in th.name for m in ctx.exclude.split(',')):
                            pass
                        else:
                            th.switch()
                            frame = gdb.newest_frame()
                            while (frame.older() != None):
                                frame = frame.older()
                            self.threads[thn].function.inverse_add_frame(frame)

                samples += 1
                gdb.write(".")
                gdb.flush(gdb.STDOUT)
        except KeyboardInterrupt:
            pass
        finally:
            print(("\nProfiling complete with %d samples." % samples))
            if ctx.output:
                common.dump_threads(self.threads, ctx.output)
            else:
                common.print_callgraph(self.threads)

        if detach_and_kill:
            gdb.execute("detach", to_string=True)
            gdb.execute("quit")
        else:
            pid = gdb.selected_inferior().pid
            os.kill(pid,
                    signal.SIGSTOP)  # Make sure the process does nothing until
            # it's reattached.
            gdb.execute("detach", to_string=True)
            gdb.execute("attach %d" % pid, to_string=True)
            os.kill(pid, signal.SIGCONT)
            gdb.execute("continue", to_string=True)