GDB: setting complex break point with condition involving variable from previous frame - gdb

Is it possible to set a complex breakpoint which has condition which involves check on the argument passed to the outer function(frame).
eg.
1 #0 sample::_processMessage (this=0xa5c8c0, data=0x7fffe5ae31db "\027w\270߸\023\032\212\v", line=0x7fffe4799db8 "224.4.2.197:60200", should_process=true) a sample.cpp:426
2 #1 0x00007ffff682f05d in sample::_process (this=0xa5c8c0, should_process=true, line=0x7fffe4799db8 "224.4.2.197:60200", data=0x7fffe5ae31db "\027w\270߸\023\032\212\v", sn=31824) a sample.cpp:390
3 #2 0x00007ffff6836744 in sample::drain (this=0xa5c8c0, force=true) at sample.cpp:2284
4 #3 0x00007ffff682ed81 in sample::process (this=0xa5c8c0, mdData=0x7fffe67914e0) at sample.cpp:354
Here I want to set a break point on sample.cpp:356,which is on in the function process-frame#3,
if the _process or frame #1 at the time hitting breakpoint has sn == 31824
so actually break point is at function _process but I want pause the execution in the function process
Thanks in advance

I don't know if it's possible to create conditional breakpoints that reference an outer frame, but you could use breakpoint commands to achieve a similar result.
Here's an example gdb session:
(gdb) break some-location
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>silent
>up
>if (sn != 31824)
>continue
>end
>end
Now every time gdb hits the breakpoint it will automatically move up a frame, check sn and continue if the value is not correct. This will not be any (or much) slower than a conditional breakpoint, and the only real downside is that it will print out a line each time the breakpoint is hit, even if gdb then continues.
The silent in the command list cuts down on some of the normal output that is produced when a breakpoint is hit, this can be removed to get a more verbose experience.

This can be accomplished with a gdb convenience function implemented in python:
import gdb
class CallerVar(gdb.Function):
"""Return the value of a calling function's variable.
Usage: $_caller_var (NAME [, NUMBER-OF-FRAMES [, DEFAULT-VALUE]])
Arguments:
NAME: The name of the variable.
NUMBER-OF-FRAMES: How many stack frames to traverse back from the currently
selected frame to compare with.
The default is 1.
DEFAULT-VALUE: Return value if the variable can't be found.
The default is 0.
Returns:
The value of the variable in the specified frame, DEFAULT-VALUE if the
variable can't be found."""
def __init__(self):
super(CallerVar, self).__init__("_caller_var")
def invoke(self, name, nframes=1, defvalue=0):
if nframes < 0:
raise ValueError("nframes must be >= 0")
frame = gdb.selected_frame()
while nframes > 0:
frame = frame.older()
if frame is None:
return defvalue
nframes = nframes - 1
try:
return frame.read_var(name.string())
except:
return defvalue
CallerVar()
It can be used like:
(gdb) b sample.cpp:356 if $_caller_var("sn",2)==31824

Related

Using multiple try: except to handle error does not work

I have a list of files I am iterating through:
condition = True
list = ['file1', 'file2', 'file3']
for item in list:
if condition == True
union = <insert process>
....a bunch of other stuff.....
Let's say the code works fine on file1 and file3, but when it gets to file2, an IO error gets thrown. What I want to do is route around file2 when the IOError is thrown a go to back to the next item in the list. I want to use a try: except method to do this but I can't seem to get it right. Note: I have an overall try-catch at the beginning of the code. I am not sure if it may interfere with having a second one on just a specific section of the code.
try:
try:
condition = True
list = ['file1', 'file2', 'file3']
for item in list:
if condition == True
union = <insert process>
....a bunch of other stuff.....
except IOError:
continue
.....a bunch more stuff.....
except Exception as e:
logfile.write(e.message)
logfile.close()
exit()
What is the difference between 'pass' and 'continue' and is why would the above code not work? Do I need to add more specific information to the IOError part?
What's the difference between pass and continue ?
pass is a no-op, it tells python to simply do nothing and go to the next instruction.
continue is a loop operation, it tells python to ignore whatever else code is left in this iteration of the loop and simply go to the next iteration as if it had reached the end of the loop block.
For example:
def foo():
for i in range(10):
if i == 5:
pass
print(i)
def bar():
for i in range(10):
if i == 5:
continue
print(i)
The first will print 0,1,2,3,4,5,6,7,8,9, but the second will print 0,1,2,3,4,6,7,8,9 because the continue statement will cause python to jump back to the start and not go on to the print instruction, whereas pass will continue executing the loop normally.
Why would the above code not work?
The issue with your code is that the try block is outside the loop, once an exception occurs inside the loop, the loop terminates at that point and jumps to the except block outside the loop. To fix that, just move the try and except blocks into your for loop:
try:
condition = True
list = ['file1', 'file2', 'file3']
for item in list:
try:
# open the file 'item' somewhere here
if condition == True
union = <insert process>
....a bunch of other stuff.....
except IOError:
# this will now jump back to for item in list: and go to the next item
continue
.....a bunch more stuff.....
except Exception as e:
logfile.write(e.message)
logfile.close()
exit()

Trying to reference a variable before assignment inside a recursive function

#!/usr/bin/python
import sys
def Count_Totals(lst): # returns an array with the number of elements in each level on nesting
for el in lst:
if type(el)==list:
temp=el
index = index + 1 # this is index of Counts which indicates the level of nesting
Count_Totals(el)
else:
Counts[index] = Counts[index] + 1 # When we reach the bottom nest to count elements
Size = Size + 1
if Size == len(temp) - 1:
index = index - 1 # When list inside list runs out of elements
in_file = sys.argv[1]
with open(in_file,'r') as input_file:
lines = input_file.readlines() # reads entire ascii file and
saves into a list called lines
Frame = 0
Size = 0
index = 0
for line in lines: # creates a list of each row in text file
Counts = []
Frame = Frame + 1
Count_Totals(line) #Counts the elements in each level of nest
print("The Frame contains: %d subrames, which is %d Symbols", Count[0] , Count [1])
Hello, I am trying to write a python 2.7 program which takes in a text file that has nested lists and count the number of items in each level of list and outputs the values as a print statement. I have written the preceding code using recursion but I am having trouble running with the following error:
UnboundLocalError: local variable 'index' referenced before assignment
My understanding is that the index inside the function is outside the scope of the index variable I initialized at the bottom. Any help to fix this code or get it up and running would be greatly appreciated.
It looks to me like you don't want to access a local variable named index. You want to access a global named index, which is what you initialized to 0 later on.
When python sees a variable used for the first time in a function, it has to figure out whether you intended it to be a global or a local. It errs on the side of it being a local. In particular, if you assign to the value, it assumes it is a local (the exact rules are here).
To fix this, all you have to do is add a global statement into your function. That tells Python that the specified variables are actually globals.
def Count_Totals(lst):
global index
for el in lst:

Python - how do I display an updating value on one line and not scroll down the screen

I have a python script which receives values in real-time. My script prints the values as they are received and currently, each update is printed to the screen and the output scrolls down e.g.
Update 1
Update 2
Update 3
...
Is it possible to have each new value overwrite the previous value on the output screen so that the values don't scroll? e.g.
Update 1
When Update 2 is received the print statement would update the output screen to:
Update 2
and so on...
Thanks in advance for any pointers.
You can pass end='\r' to the print() function. '\r' represents a carriage return in Python. In Python 3 for example:
import time
for i in range(10):
print('Update %d' % i, end='\r')
time.sleep(5)
Here time.sleep(5) is just used to force a delay between prints. Otherwise, even though everything is being printed and then overwritten, it will happen so fast that you will only see the final value 'Update 9'. In your code, it sounds like there is a natural delay while some processes is running, using time.sleep() will not be necessary.
In python 2.7, the print function will not allow an end parameter, and print 'Update %d\r' will also print a newline character.
Here is the same example #elethan gave for python2.7. Note it uses the sys.stdout output stream:
import sys
import time
output_stream = sys.stdout
for i in xrange(10):
output_stream.write('Update %s\r' % i)
output_stream.flush()
time.sleep(5)
# Optionally add a newline if you want to keep the last update.
output_stream.write('\n')
Assuming you have your code which prints the updated list in write_num function,
You can have a function called show_updated_list().
Hoping the clear() every time should resolve this issue:
def show_updated_list():
self.clear()
write_num()

Any ideas for why two side by side print statements in python would not execute?

I have a class defined as this:
class decider(object):
def __init__(self, brain):
self.brain = brain
##stuff
## brain is an object
In a class function I have two print statements, right next to each other, like so:
def somefunction(self, someParam):
print "Something First"
print "Another something: " + self.brain.aVariable + ", " + self.brain.anotherVariable
# more stuff
# execution continues as normal
# the object called in brain exists (ive checked)
In another function (in the same class) I call this function.The first print statement is printing, the second one is not. No exceptions are raised and the code just skips that line. No crashes either. I find this pretty bizarre and had not happened to me until now. Is there a reason for why this could possibly be happening?
If it matters, I'm running python 2.7 on an embedded system with an ATOM Z530 processor.
Could be buffered? Does anything print after the second call?
Add another print after the second call to force to clear the buffer

How do I make GDB call a given function several times automatically?

I'd like to make GDB call a given function a large number of times automatically, say 100. Is there any command that will let me do that?
Save this example script into a file say my_gdb_extensions
define fcall_n_times
set $count = $arg0
set $i=0
while($i < $arg0)
call $arg1
set $i = $i + 1
end
end
You can find more about gdb extensions here.
$ gdb -x my_gdb_extensions <your_bin>
(gdb) start
(gdb) fcall_n_times 10 fact(3)
In the mentioned example 10 is the number of times you want to call the function. fact(3) is the function name with argument as 3.