简体   繁体   中英

GDB not stopping with "interrupt" command from python script

I've been ripping my hair out over this. I've searched the internet and can't seem to find a solution to my problem. I'm trying to auto test some code using the gdb module from python. I can do basic command and things are working except for stopping a process that's running in the background. Currently I continue my program in the background after a break point with this:

gdb.execute("c&")

I then interact with the running program reading different constant values and getting responses from the program.
Next I need to get a chunk of memory so I run these commands:

gdb.execute("interrupt") #Pause execution gdb.execute("dump binary memory montiormem.bin 0x0 (&__etext + 4)") #dump memory to file

But when I run the memory dump I get an error saying the command can't be run when the target is running, after the error the interrupt command is run and the target is paused, then from the gdb console window I can run the memory dump.

I found a similar issue from awhile ago that seems to not be answered here .

I'm using python2.7.

I also found this link which seems to be the issue but no indication if it's in my build of gdb (which seems unlikely).

I just ran into this same issue while writing some automated testing scripts. What I've noticed is that the 'interrupt' command doesn't stop the application until after the current script has exited.

Unfortunately, this means that you would need to segment your scripts anytime you are causing an interrupt.

Script 1:

gdb.execute('c&')
gdb.execute('interrupt')

Script 2:

gdb.execute("dump binary memory montiormem.bin 0x0 (&__etext + 4)")

I used multi threading to get arround this issue:

def post(cmd):
    def _callable():
        print("exec " + cmd , flush=True)
        gdb.execute(cmd)

    print("schedule " + cmd , flush=True)
    gdb.post_event(_callable)

class ScriptThread (threading.Thread):
    def run (self):

        while True:
            post("echo hello\n")
            time.sleep(1)

x = ScriptThread()
x.start()

Save this as "test_script.py"

Use the script as follows:

gdb
> source test_script.py

Note: that you can also pipe "source test_script.py", but you need to keep the pipe open.

Once the thread is started GDB will wait for the thread to end and will process any commands you send to it via the "post_event" function. Even "interrupt"!

I had the same problem, from what I can tell from googling it is a current limitation of gdb: interrupt simply doesn't work in batch mode (when specifying commands with --ex , or -x file , or on stdin, or sourcing from file), it runs the following commands before actually stopping the execution (inserting a delay doesn't help). Building on the @dwjbosman's solution, here's a compact version suitable for feeding to gdb with --ex arguments for example:

python import threading, gdb
python threading.Timer(1.0, lambda: gdb.post_event(lambda: gdb.execute("interrupt"))).start()
cont
thread apply all bt full # or whatever you wanted to do

It schedules an interrupt after 1 second and resumes the program, then you can do whatever you wanted to do after the pause right in the main script.

I had the same problem, but found that none of the other answers here really work if you are trying to script everything from python. The issue that I ran into was that when I called gdb.execute('continue') , no code in any other python thread would execute. This appears to be because gdb does not release the python GIL while the continue command is waiting for the program to be interrupted.

What I found that actually worked for me was this:

def delayed_interrupt():
    time.sleep(1)
    gdb.execute('interrupt')
gdb.post_event(delayed_interrupt)
gdb.execute('continue')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM