import gdb
breakpoints = []
registers = []
gdb.execute('rbreak') # Set breakpoints at every function call
gdb.execute('run') # run (until break)
while True:
a = gdb.execute('continue', to_string=True)
info_reg = gdb.execute('info registers rip', to_string=True)
info_break = gdb.execute('info breakpoints', to_string=True)
gdb.execute('disable breakpoints ' + e)
registers .append(info_reg)
breakpoints.append(info_break)
if programClose:
break
f = open("output", "w+")
[f.write(b + '\n') for b in breakpoints]
f.close()
I'm trying to attach a debugger to a running process and I want to set breakpoints on every call. For every breakpoint I run into I indend to be in the while loop and save some information about the breakpoints. However my python code gets stuck on printing every breakpoint to the console after gdb.execute('rbreak') # Set breakpoints at every function call. Is it possible to do what I intend?
Related
I'm debugging C++ code with GDB and when it enters a constructor of some object containing standard library objects, it shows me the constructor of these objects (like std::map) and everything that's underneath.
I know about the next operator, but I'd prefer to basically black list any standard library code, which is never the source of the error I'm investigating. The wished behavior is that a simple skip would send me to the next "user-land" code.
gdb 7.12 supports file globbing to specify the files to skip in the debugger. The documentation for the same is as below:
https://sourceware.org/gdb/onlinedocs/gdb/Skipping-Over-Functions-and-Files.html
To skip stepping into all library headers in the directory /usr/include/c++/5/bits, add the below lines to ~/.gdbinit
# To skip all .h files in /usr/include/c++/5/bits
skip -gfi /usr/include/c++/5/bits/*.h
Instead to skip a specific file, say stl_vector.h, add the below lines to ~/.gdbinit
# To skip the file /usr/include/c++/5/bits/stl_vector.h
skip file /usr/include/c++/5/bits/stl_vector.h
Doing the above with gdb 7.11 and below version leads to the below error:
Ignore function pending future shared library load? (y or [n]) [answered N; input not from terminal]
However, gdb 7.12 seems to have solved the above issue.
This blog addresses the same problem for gdb version 7.11 or below.
Note - You can use the below command from the gdb command prompt to list all the files marked for skipping
info skip
* Changes in GDB 7.4
GDB now allows you to skip uninteresting functions and files when stepping with the "skip function" and "skip file" commands.
Step instructions and skip all files without source
This will be too slow for most applications, but it is fun!
Based on: Displaying each assembly instruction executed in gdb
class ContinueUntilSource(gdb.Command):
def __init__(self):
super().__init__(
'cus',
gdb.COMMAND_BREAKPOINTS,
gdb.COMPLETE_NONE,
False
)
def invoke(self, argument, from_tty):
argv = gdb.string_to_argv(argument)
if argv:
gdb.write('Does not take any arguments.\n')
else:
done = False
thread = gdb.inferiors()[0].threads()[0]
while True:
message = gdb.execute('si', to_string=True)
if not thread.is_valid():
break
try:
path = gdb.selected_frame().find_sal().symtab.fullname()
except:
pass
else:
if os.path.exists(path):
break
ContinueUntilSource()
Tested in Ubuntu 16.04, GDB 7.11. GitHub upstream.
std::function case
How to step debug into std::function user code from C++ functional with GDB?
Modified from Ciro Santilli's answer command ss steps inside specific source. You may specify source file name or the current one will be stepped. Very handy for stepping through bison/yacc sources or other meta-sources that generate ะก code and insert #line directives.
import os.path
class StepSource(gdb.Command):
def __init__(self):
super().__init__(
'ss',
gdb.COMMAND_BREAKPOINTS,
gdb.COMPLETE_NONE,
False
)
def invoke(self, argument, from_tty):
argv = gdb.string_to_argv(argument)
if argv:
if len(argv) > 1:
gdb.write('Usage:\nns [source-name]]\n')
return
source = argv[0]
full_path = False if os.path.basename(source) == source else True
else:
source = gdb.selected_frame().find_sal().symtab.fullname()
full_path = True
thread = gdb.inferiors()[0].threads()[0]
while True:
message = gdb.execute('next', to_string=True)
if not thread.is_valid():
break
try:
cur_source = gdb.selected_frame().find_sal().symtab.fullname()
if not full_path:
cur_source = os.path.basename(cur_source)
except:
break
else:
if source == cur_source:
break
StepSource()
Known bugs
it doesn't interrupt debugger on SIGINT while running;
changed pass to break on exception as not sure whether it is right.
I'm trying to run a pygame program using pythonw to avoid having the console window show up. This causes a weird issue related to print statements.
Basically, the program will just exit after a few seconds with no error message. The more printing I do, the faster it happens.
If I run it in idle or at the command prompt (or in linux) the program works fine. This problem only happens when launched with pythonw (right-click, Open With, pythonw).
I'm using python 2.7.11 on Windows XP 32-bit. pygame 1.9.1release.
Is there a workaround for this? Why does the program simply terminate with no error?
import pygame
from pygame.locals import *
succeeded, failed = pygame.init()
display_surface = pygame.display.set_mode((320, 240))
clock = pygame.time.Clock()
terminate = False
while terminate is False:
for event in pygame.event.get():
if event.type == QUIT:
terminate = True
area = display_surface.fill((0,100,0))
pygame.display.flip()
elapsed = clock.tick(20)
print str(elapsed)*20
pygame.quit()
You don't need to remove print statements. Save them for later debugging. ;-)
Two steps to solve this problem:
Firstly, keep all the code in py file - don't change it to pyw now; Say it is actualCode.py
Then, create a new file runAs.pyw with the following lines in it
# In runAs.pyw file, we will first send stdout to StringIO so that it is not printed
import sys # access to stdout
import StringIO # StringIO implements a file like class without the need of disc
sys.stdout = StringIO.StringIO() # sends stdout to StringIO (not printed anymore)
import actualCode # or whatever the name of your file is, see further details below
Note that, just importing actualCode runs the file, so, in actualCode.py you should not enclose the code which is executed, in what I call is it main running file condition. For example,
# In actualCode.py file
....
....
....
if __name__ == '__main__': # Don't use this condition; it evaluates to false when imported
... # These lines won't be executed when this file is imported,
... # So, keep these lines outside
# Note: The file in your question, as it is, is fine
WinDBG and the related windows kernel debuggers support a "pc" command which runs the target until reaching the next call statement (in assembly). In other words, it breaks just prior to creating a new stack frame, sort of the opposite of "finish". "Start" in GDB runs until main starts, but in essence I want 'start' but with a wildcard of "any next frame".
I'm trying to locate a similar functionality in GDB, but have not found it.
is this possible?
Example WinDBG doc: http://windbg.info/doc/1-common-cmds.html#4_expr_and_cmds
Simple answer: no, step-to-next-call is not part of GDB commands.
GDB/Python-aware answer: no, it's not part of GDB commands, but it's easy to implement!
I'm not sure to understand if you want to stop before or after the call instruction execution.
To stop before, you need to stepi/nexti (next assembly instruction) until you see call in the current instruction:
import gdb
class StepBeforeNextCall (gdb.Command):
def __init__ (self):
super (StepBeforeNextCall, self).__init__ ("step-before-next-call",
gdb.COMMAND_OBSCURE)
def invoke (self, arg, from_tty):
arch = gdb.selected_frame().architecture()
while True:
current_pc = addr2num(gdb.selected_frame().read_register("pc"))
disa = arch.disassemble(current_pc)[0]
if "call" in disa["asm"]: # or startswith ?
break
SILENT=True
gdb.execute("stepi", to_string=SILENT)
print("step-before-next-call: next instruction is a call.")
print("{}: {}".format(hex(int(disa["addr"])), disa["asm"]))
def addr2num(addr):
try:
return int(addr) # Python 3
except:
return long(addr) # Python 2
StepBeforeNextCall()
To stop after the call, you compute the current stack depth, then step until it's deeper:
import gdb
def callstack_depth():
depth = 1
frame = gdb.newest_frame()
while frame is not None:
frame = frame.older()
depth += 1
return depth
class StepToNextCall (gdb.Command):
def __init__ (self):
super (StepToNextCall, self).__init__ ("step-to-next-call",
gdb.COMMAND_OBSCURE)
def invoke (self, arg, from_tty):
start_depth = current_depth =callstack_depth()
# step until we're one step deeper
while current_depth == start_depth:
SILENT=True
gdb.execute("step", to_string=SILENT)
current_depth = callstack_depth()
# display information about the new frame
gdb.execute("frame 0")
StepToNextCall()
just put that in a file, source it with GDB (or in your .gdbinit) and that will provide you the new commands step-before-next-call and step-to-next-call.
Relevant documentation is there:
Python API table of content
Basic Python
Python representation of architectures
Accessing inferior stack frames from Python.
How can I print out the output of an external command by characters or at least by lines?
This code prints it in one block after the command returns.
import subprocess as sub
output, errors = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate()
print output + errors
You can access to the standart output stream as
p = sub.Popen("cmd", stdout=sub.PIPE, stderr=sub.PIPE)
print(p.stdout.readline()) # This read a line
You can perform any operation o the file streams.
When you use readline in a standart output of a proccess the main thread of the app wait for that proccess to write some thing on the ouput. When that process write to the output you program continue.
You must know that before read a line from the proceess you need to call flush() on the stream. Because the streams have a cache time before the real values are written to it.
You can see this post, this is a good explanation of how this work on python
http://www.cyberciti.biz/faq/python-execute-unix-linux-command-examples/
import subprocess
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
while True:
out = p.stderr.read(1)
if out == '' and p.poll() != None:
break
if out != '':
sys.stdout.write(out)
sys.stdout.flush()
It prints out the output of the cmd character by character.
I want to set a "rolling" breakpoint in gdb; there just print the current source line with some info; and then continue. I start with something like this:
break doSomething
commands
continue
end
This, on its own, prints out:
Breakpoint 1, doSomething () at myprog.c:55
55 void doSomething() {
I wanted to remove the "Breakpoint X ... at ..." message, which can be done with silent - and then printout just the source line; so I tried:
break doSomething
commands
silent
list
continue
end
This results with 10 lines of listing, like below
50 // some comments
...
55 void doSomething() {
...
59 // other comments
The problem is, saying list 1 will again give 10 lines, just starting from the first line; while doing list +0,+0 will indeed provide one line of source only - but the wrong line (in my case, it gives line 50).
So, then I realized that one can get and print the current program address by using the program counter $pc - and given that one can also list around a program address, I tried this:
break doSomething
commands
silent
#print $pc
list *$pc,+0
continue
end
This results with correct source line - but for some reason, again with an extra message, this time "ADDR is in X ..." :
0x8048fe0 is in doSomething (myprog.c:55).
55 void doSomething() {
Any ideas how to get only the source line to print?
As a sub-question - is it possible somehow to capture the output of the list command, and use it as an argument to printf in the gdb scripting dialect? (I'm pretty sure capturing gdb command output can be done through the python gdb scripting, though)...
Well, I think I got somewhere better with gdb's Python; now I can get the output to look like this (using gdb 7.3.50.20110806-cvs):
[ 56] 0x8048fe0 myprog.c:55 void doSomething() {
[ 56] 0x8049058 myprog.c:63 }
For the most part, I tried to use Symbol-Tables-In-Python to get to this (turns out there was an SO question about this, too: gdb find memory address of line number).
But, for some reason, when I use Symtab_and_line.line, which "Indicates the current line number for this object", it doesn't seem to change? In the above example, it is the first number in square brackets, and sits constantly at 56 (and is wrong in both cases). One would have hoped that the API would have had all that covered; and while the line number is there (albeit wrong?) - I couldn't find the string content of the respective source code line, as an object attribute, anywhere. On the other hand, when I use gdb.execute("list *$pc,+0") to query gdb directly about the current line as per OP, I get correct line numbers - but then, I have to additionally split and parse strings in Python :/
Still, better than nothing - here's the (Python embedded in gdb script) code; just throw it in your .gdbinit:
python
# example: these breakpoints do stop - but cannot change their
# stop method (which contains the "commands" for breakpoint in python)
#ax = gdb.Breakpoint("doSomething")
#print("hello", ax)
#print(dir(ax))
#print(ax.expression, ax.condition, ax.commands) # not writable!
#bx = gdb.Breakpoint("myprog.c:63")
# anything more than that - need to subclass:
class MyBreakpoint(gdb.Breakpoint):
def __init__(self, spec, command=""):
super(MyBreakpoint, self).__init__(spec, gdb.BP_BREAKPOINT,
internal = False)
self.command = command # not used
def stop(self):
# gdb.write - like print
# gdb.decode_line() - like gdb.find_pc_line(pc)
current_line = gdb.decode_line()
symtline = current_line[1][0]
#print(current_line, symtline.is_valid(), symtline.line , symtline.pc , symtline.symtab )
sysy = symtline.symtab
#print(sysy.filename, sysy.fullname(), sysy.is_valid() )
sysyo = sysy.objfile
#print(sysyo.filename, sysyo.is_valid(), sysyo.pretty_printers)
###print(gdb.solib_name()) # this breaks stuff??!
sourcefilename = sysy.filename
sourcefullpath = sysy.fullname()
sourcelinenum = symtline.line # somehow, it may be offset by 1, from what "list *$pc says"
listingline = gdb.execute("list *$pc,+0", to_string=True)
#print( "BREAK at %s:%d -- %s" % (sourcefilename, sourcelinenum, listingline) )
llsplit = listingline.split("\n")
listpreamble, gdbsourceline = llsplit[:2]
addr, noneed, noneed, funcname, fileloc = listpreamble.split(" ")[:5]
#linenum, sourceline = gdbsourceline.split("\t")[:2] # not using these - put gdb line verbatim
outline = "[% 4s] %s % 16s:%s" % (sourcelinenum, addr, sourcefilename[-16:], gdbsourceline)
print(outline)
return False # continue (do not stop inferior)
ax = MyBreakpoint("doSomething")
bx = MyBreakpoint("myprog.c:63")
end
run