Xcode All Exceptions Breakpoint - Ignore Certain C++ Exception - c++

I'm coding in C++ for iOS, using certain iOS Frameworks like AVAudioPlayer. I know that these can trigger C++ exceptions internally and it's perfectly fine, since they catch and handle them.
I would like to use the All Exceptions Breakpoint in Xcode to break on Crash-Issues in my own C++ code, but to ignore that AVAudioPlayer's C++ exceptions (and basically all other catched exceptions).
How can I achieve that?

There isn't a way to do this using the Xcode breakpoint settings.
You can do this in lldb using a Python breakpoint command on the C++ exception breakpoint. Your callback would look up the stack to the point where the exception is thrown, and check that the throwing code is in your shared library, and auto-continue from the breakpoint or not.
The section in:
http://lldb.llvm.org/python-reference.html
on running a script when a breakpoint is hit will give you some details about how to do this.
For instance, you could put:
module_name = "TheNameOfYourExecutableOrSharedLibrary"
def bkpt_cmd (frame, loc, dict):
global module_name
thread = frame.GetThread()
frame_1 = thread.GetFrameAtIndex(1)
module = frame_1.GetModule()
name = module.GetFileSpec().GetFilename()
if module_name in name:
return True
return False
in a file called ~/bkpt_cmd.py. Then in the lldb console, do:
(lldb) br s -E c++
Breakpoint 1: no locations (pending).
(lldb) command script import ~/bkpt_cmd.py
(lldb) br com add -F bkpt_cmd.bkpt_cmd
This will set a C++ exception breakpoint that only triggers when the raising frame is in the shared library called "TheNameOfYourExecutableOrSharedLibrary"...
BTW, if you put the following def in your .py file:
def __lldb_init_module(debugger, internal_dict):
it will get run when the command script import command is executed, so you could use this to add the breakpoint and the command to the breakpoint at one go. I'll leave that as an exercise for the reader.
Note also, this will work when running lldb within Xcode, but you'll want to make your own exception breakpoint as shown above, since Xcode has a different way of handling the commands for the breakpoints it manages.

Related

breakpoint at end of a function

I am trying to log the input and output of a function via gdb script. below is a sample script.
set logging on
b func2
commands
silent
bt 1
continue
end
b func1
commands
silent
bt 1
set logging off
continue
end
It works fine and breakpoints at the specified functions, prints the backtrace and continues.
is there a way to automatically set a breakpoint just before the called function returns to the calling function, so that I can just print output variables via gdb just after this "new" breakpoint.
This will greatly simplify my debug, and help understand the function behavior for different calls in the code.
Any help is highly appreciated.
Thanks a lot in advance !
I have looked into this and cannot find a way to do this with normal GDB breakpoints.
It is possible to implement using the GDB Python extensions API.
source-ing a file with the following content (source FILENAME) from with GDB will allow one to issue the command break-return which will place a temporary break-point at every 'return' in the current file (this is overkill but works). Once any one of the breakpoints is hit they are all deleted.
import gdb
class _ReturnBreakpoint(gdb.Breakpoint):
def stop(self):
for breakpoint in self._siblings:
if breakpoint.number != self.number:
gdb.execute(f"d {breakpoint.number}")
return True
class _BreakReturn(gdb.Command):
def __init__(self):
super(_BreakReturn, self).__init__("break-return", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
function_name = gdb.selected_frame().name()
source_file = gdb.selected_frame().find_sal().symtab.filename
breakpoints = []
with open(source_file) as o:
for zero_based_index, line in enumerate(o.readlines()):
if not 'return ' in line:
continue
breakpoint = _ReturnBreakpoint(line=zero_based_index+1, temporary=True)
breakpoints.append(breakpoint)
for breakpoint in breakpoints:
breakpoint._siblings = breakpoints
_BreakReturn() # register the command with GDB
Taken from https://github.com/jbcoe/GDB-extensions/blob/master/extensions/break-return.py
Patches are welcome.

GDB script flow control for remote target

I would like to do only flash the code on a remote gdb target if it has changed since last time gdb was run. I envisage something along the lines of the following in gdb script;
target extended-remote /dev/<device>
<Attach to Target>
file <Target Program>
if ![compare-sections -r]
load
start
...however, I cannot see how to make a conditional on a command output.
Can anyone help? I think I probably missed something, but I've no idea what....
The compare-sections command doesn't return a value that can be used in an if statement, but the following may do what you want.
First, define a convenience function named $cmdeval which will execute a gdb command and return its output as a string:
import gdb
class CmdEval(gdb.Function):
"""$cmdeval(str) - evaluate argument string as a gdb command
and return the result as a string. Trailing newlines are removed.
"""
def __init__(self):
super(CmdEval, self).__init__("cmdeval")
def invoke(self, gdbcmd):
return gdb.execute(gdbcmd.string(), from_tty=False, to_string=True).rstrip('\n')
CmdEval()
You can put this in a file named cmdeval.py and type (gdb) source cmdeval.py to load it into gdb.
Next, since compare-sections outputs "MIS-MATCHED" for any section that has been changed, you can look for that string using the $_regex convenience function, which is included in more recent versions of gdb:
(gdb) if $_regex($cmdeval("compare-sections -r"),".*MIS-MATCHED.*")
>echo need to load again\n
>end

How to set breakpoint in catch block? (c++)

There is something strange happening when I try to debug application. Simply the debugger does not stop on breakpoints when I set breakpoints in catch portion of try-catch block.
Here is an example.
try {
throw std::overflow_error("test");
} catch (...) {
qDebug() << "caught"; // HERE, I SET BREAKPOINT ON THIS LINE
}
It prints the "caught" on screen when exception occurs but it does not stop on this line. (If you ever wonder; Yes, I'm building app in Debug mode and running in Debug mode)
Am I suffering from lack of fundamental knowledge about how gdb works? (I mean maybe it does not stop because breakpoints in catch portion does not work)
Any help would be greatly appreciated.
Thanks.
To catch an exception in IDE, you need issue gdb commands directly in gdb console.
Here's link how to get into gdb console in Qt Create IDE:
Accessing gdb console in Qt-Creator
Once you're the type
catch throw
to stop when your program throws an exception or
catch catch
to stop in the catch block.
If you need to catch a specific library exception, read this thread: GDB: How to break when a specific exception type is thrown?
for people using LLDB,
# set on both throw and catch
breakpoint set -E C++ -h true
# or on catch
b __cxa_begin_catch
# or on throw
b __cxa_throw
while will set breakpoints on throw and catch.
#ben sen, I guess any opinization may result in such a behavior. There are many ways how those options can be specified (via environment variables aka CFLAGS or via IDE options to the project), but they all result to some particular -O option given to the compiller command line. Even if nothing is given at all, please check what is the default optimization for your compiller. My proposal would be to explicitely give -O0 to the compiller and check that no other -O options are supplied.

Prevent PLT (procedure linkage table) breakpoints in GDB

In recent versions of GDB, setting a breakpoint on a library function call results in multiple actual breakpoints:
Call into the procedure linkage table (PLT)
The actual function call
This means that when the library function is called, we end up going through two breaks each time. In previous GDB versions, only #2 would be created and hence you only get one break.
So the question is: can one can create a library function call breakpoint without the corresponding PLT breakpoint? I am aware that you can create a regular breakpoint and then explicitly disable the PLT one, but this is really tedious.
I think I found a solution for this problem. You can use the
break *address
syntax of break, but instead of specifying a hex address, you give the name of the function (which evaluates to the function's address). Something like
break *myfunction
That sets a breakpoint only on the main function, and not any of the PLT versions.
add these lines to your ~/.gdbinit file and call disaplts to disable all #plt breakpoints:
define disaplts
python
import gdb
from StringIO import StringIO
lines=gdb.execute("info break", True, True)
for l in StringIO(lines).readlines():
if "#plt" in l:
bp=l.split()[0]
gdb.execute("disa {0}".format(bp))
print("disabling {0}".format(bp))
end
end
# disable on library load
catch load mylibrarywithplt disaplt
Note: mind the spacing in python code. I recommend you use cat to paste the content.
EDIT: added "execute on library load" per #WallStProg
Yup, it can be done.
To simply place breakpoints on all functions, use command:
rbreak .*
So, this will place breakpoints on all the functions including PLT.
Now type:
save breakpoints filename
This will save a list of all breakpoints in a file called as filename.
Now open the file in normal text editor like gedit, and remove all the PLT lines given at the end of the file. And then save the file with only the required functions on which you want to place breakpoints.
or
Remove all the #plt from the function names using the command:
sed 's/#plt//g' filename > newfilename
After this, exit gdb (to unlink gdb from useless PLT breakpoints, added before) and execute gdb again.
Now type command:
source filename
or
source newfilename (in case you used sed command)
At this point, gdb will put breakpoints only on the functions mentioned in the file called as "filename" or "newfilename" (if used sed).
Note: To filter functions more in the file "filename", one can use grep also according to the requirements. :)
Here's a command, rdelete, that is like delete in the same way that rbreak is like break - it deletes breakpoints based on a regexp argument.
$ cat rdelete.py
import gdb
import re
class RDelete(gdb.Command):
"""Delete breakpoints for all locations matching REGEXP."""
def __init__(self):
super (RDelete, self).__init__ ("rdelete", gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_LOCATION)
def invoke(self, argstr, from_tty):
bppat = re.compile(argstr)
for bp in gdb.breakpoints():
if bppat.search(bp.location):
print("Deleting breakpoint {} at {}".format(bp.number, bp.location))
bp.delete()
RDelete()
$ gdb -q hoist
(gdb) rbreak .*
...
(gdb) i b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000000580 in main at hoist.c:6
2 breakpoint keep y 0x00000000000007a0 in x at hoist.c:4
3 breakpoint keep y 0x0000000000000530 <_init>
4 breakpoint keep y 0x0000000000000560 <printf#plt>
5 breakpoint keep y 0x00000000000007b0 <__libc_csu_init>
6 breakpoint keep y 0x0000000000000820 <__libc_csu_fini>
7 breakpoint keep y 0x0000000000000824 <_fini>
(gdb) source rdelete.py
(gdb) rdelete #plt
Deleting breakpoint 4 at printf#plt

How to do a specific action when ANY Unknown Breakpoint gets Hit in GDB

I have read the following SO question:
Do specific action when certain breakpoint hits in gdb
Here, we use 'command' to decide what to do when the SPECIFIED Breakboint Gets Hit.
My Question is:
Suppose I put Breakpoints on ALL the Functions matching a given pattern:
gdb$rbreak func_
=> 100 Breakpoints (say)
When I execute this Code, I want to do the SAME Action - on hitting Each of these functions.
Hence, I cannot define something like:
command break_point_number
// since I don't know how many breakpoints will be there
Can somebody please suggest me:
How can I do a specific action-set when ANY Breakpoint gets Hit in GDB?
Thanks.
With a new enough version of gdb you can use a range:
(gdb) rbreak whatever
... gdb creates breakpoints N, N+1, ..., M
(gdb) commands N-M
> stuff
> end
I forget exactly when this feature went in.
With an older version of gdb, I'm not sure it can easily be done.
It can be done with difficulty: use set logging to write output to a file, then "info break", then "shell" to run scripts to edit the file into gdb commands, then "source". This is very painful.