I'm unable to understand how the mock-debugger extension controls where the next step is.
For example what if I'd like to step 2 lines if I find the word "banana" in my text? Also, I'd like to do something, like "Step In", where I can walk word-by-word - is it possible?
I've seen the this._currentLine = ln; assign, which looks like it controls where the line is, but it's just a simple local variable. How could it ever control anything in the debugger? I can't find any other uses of the _currentLine varbiable where it passes to anything useful API (except for stack tracing, but I don't think it has any relation with the debugger line-control).
The stack trace is the only source for the debugger step visualization. When the debugger gets a notification to pause it requests the current stack trace. The TOS determines where the next execution point will be located. Hence the debug adapter is reponsible to determine this position precisely.
I have a couple of functions in my game that in this example spawns enemies (monsters), at the very top of the function i have created a set of variables, etc:
let MonsterRandomType = arc4random_uniform(3)
let MonsterRandomRotation = arc4random_uniform(3)
And a dussin other variables that determine various properties of the enemies, the game started out as an endless runner and basically everything was made up of randomizations.
Now i decided to create levels/maps that is repeatable or have hardcoded values instead of randomness. I figured i reuse my existing functions for creating random game levels, run the game and save the random values created and use them in my hardcoded levels, i did this by setting break points on my var's and let's, iterating through them and saving as json into a file from the log, it did not work since, for whatever reason, when using random functions like arc4random_uniform the debugger and breakpoint doesn't actually set/get the value before the variable is being used further down into my code where the variables are used in if or switch statements.
If i set a breakpoint at:
let MonsterRandomType = arc4random_uniform(3)
And then test it by hitting the "Print Description" button to get more info about the variable in the output window in Xcode i will get this "error":
Printing description of MonsterRandomType:
(UInt32) MonsterRandomType = <variable not available>
Now i obviously know that i can achieve what i want (getting the value of every variable that is using a random_function) by setting the breakpoint where these variables are being used further down into the code but its very inefficient to go through many, many lines of code and many, many functions when all the variables is at the top of every function/file.
If i do the following:
print(arc4random_uniform(3))
The output window will show the value created by the random function as soon as it is created, but why cant the debugger and breakpoint show the value when it is created? Seems it can only show the value when the variable is first used further down into the code.
If i did:
let MonsterRandomType = 1
The debugger would identify the value, in the debugger it would say: "MonsterRandomType = (Int) 1". So the debugger obviously can get values as soon as the variable is created and the variable is attributed the value instantly, unless that value is created by a random_function like arc4random_uniform which is very annoying. Is it possible to fix this behaviour?
Image of breakpoint example
I'm currently trying to find a way to automate the clearing of the trace window in CANoe.
I've had a look on the help menu within CANoe but there's nothing apart from a manual x option available on the Trace window itself. Does anyone have any ideas?
Syntax
void traceWindowClear(char[] windowName);
Function
Clears the contents of the Trace Window.
Parameters
windowName - The name of the Trace Window.
Return Values
—
Availability
Since Version 11.0 In Measurement Setup and Simulation / Test Setup.
I have an All Exceptions breakpoint configured in Xcode:
Sometimes Xcode will stop on a line like:
[managedObjectContext save:&error];
with the following backtrace:
but the program continues on as if nothing happened if you click Continue.
How can I ignore these "normal" exceptions, but still have the debugger stop on exceptions in my own code?
(I understand that this happens because Core Data internally throws and catches exceptions, and that Xcode is simply honoring my request to pause the program whenever an exception is thrown. However, I want to ignore these so I can get back to debugging my own code!)
Moderators: this is similar to "Xcode 4 exception breakpoint filtering", but I think that question takes too long to get around to the point and doesn't have any useful answers. Can they be linked?
For Core Data exceptions, what I typically do is remove the "All Exceptions" breakpoint from Xcode and instead:
Add a Symbolic Breakpoint on objc_exception_throw
Set a Condition on the Breakpoint to (BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:#"_NSCoreData"])
The configured breakpoint should look something like this:
This will ignore any private Core Data exceptions (as determined by the class name being prefixed by _NSCoreData) that are used for control flow. Note that the appropriate register is going to be dependent on the target device / simulator that you are running in. Take a look at this table for reference.
Note that this technique can be adapted easily to other conditionals. The tricky part was in crafting the BOOL and NSException casts to get lldb happy with the condition.
I wrote an lldb script that lets you selectively ignore Objective-C exceptions with a much simpler syntax, and it handles both OS X, iOS Simulator, and both 32bit and 64bit ARM.
Installation
Put this script in ~/Library/lldb/ignore_specified_objc_exceptions.py or somewhere useful.
import lldb
import re
import shlex
# This script allows Xcode to selectively ignore Obj-C exceptions
# based on any selector on the NSException instance
def getRegister(target):
if target.triple.startswith('x86_64'):
return "rdi"
elif target.triple.startswith('i386'):
return "eax"
elif target.triple.startswith('arm64'):
return "x0"
else:
return "r0"
def callMethodOnException(frame, register, method):
return frame.EvaluateExpression("(NSString *)[(NSException *)${0} {1}]".format(register, method)).GetObjectDescription()
def filterException(debugger, user_input, result, unused):
target = debugger.GetSelectedTarget()
frame = target.GetProcess().GetSelectedThread().GetFrameAtIndex(0)
if frame.symbol.name != 'objc_exception_throw':
# We can't handle anything except objc_exception_throw
return None
filters = shlex.split(user_input)
register = getRegister(target)
for filter in filters:
method, regexp_str = filter.split(":", 1)
value = callMethodOnException(frame, register, method)
if value is None:
output = "Unable to grab exception from register {0} with method {1}; skipping...".format(register, method)
result.PutCString(output)
result.flush()
continue
regexp = re.compile(regexp_str)
if regexp.match(value):
output = "Skipping exception because exception's {0} ({1}) matches {2}".format(method, value, regexp_str)
result.PutCString(output)
result.flush()
# If we tell the debugger to continue before this script finishes,
# Xcode gets into a weird state where it won't refuse to quit LLDB,
# so we set async so the script terminates and hands control back to Xcode
debugger.SetAsync(True)
debugger.HandleCommand("continue")
return None
return None
def __lldb_init_module(debugger, unused):
debugger.HandleCommand('command script add --function ignore_specified_objc_exceptions.filterException ignore_specified_objc_exceptions')
Add the following to ~/.lldbinit:
command script import ~/Library/lldb/ignore_specified_objc_exceptions.py
replacing ~/Library/lldb/ignore_specified_objc_exceptions.py with the correct path if you saved it somewhere else.
Usage
In Xcode, add a breakpoint to catch all Objective-C exceptions
Edit the breakpoint and add a Debugger Command with the following command:
ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
This will ignore exceptions where NSException -name matches NSAccessibilityException OR -className matches NSSomeException
It should look something like this:
In your case, you would use ignore_specified_objc_exceptions className:_NSCoreData
See http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/ for the script and more details.
Here is an alternative quick answer for when you have a block of code e.g. a 3rd part library that throws multiple exceptions that you want to ignore:
Set two breakpoints, one before and one after the exception throwing block of code you want to ignore.
Run the program, until it stops at an exception, and type 'breakpoint list' into the debugger console, and find the number of the 'all exceptions' break point, it should look like this:
2: names = {'objc_exception_throw', '__cxa_throw'}, locations = 2
Options: disabled
2.1: where = libobjc.A.dylibobjc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0
2.2: where = libc++abi.dylib__cxa_throw, address = 0x00007fff8d19fab7, unresolved, hit count = 0
This means it is breakpoint 2. Now in xcode, edit the first breakpoint (before the exception throwing code) and change the action to 'debugger command' and type in 'breakpoint disable 2' (and set 'automatically continue...' checkbox ).
Do the same for the break point after the offending line and have the command 'breakpoint enable 2'.
The all breakpoints exception will now turn on and off so it's only active when you need it.
I'm trying to track down who is making an allocation of a certain size, and I tried using the user mode stack trace db (gflags +ust), but due to FPO I can't see the entire stack. So instead I wanted to set a breakpoint on RtlAllocateHeap when it makes the allocation size I'm looking for. The only problem is I can't seem to find out a way to get this to work.
I initially tried using #esi since it looked like the third parameter was being passed using this register, but it doesn't appear that's always the case. So then I tried #ebp-c to give me the third parameter, but that doesn't appear to always work, so I tried #esp+14 and that didn't work either.
No matter what I do I can't seem to find a way to get this to actually fire when I want it to. It seems like this should work, but I'm guessing it is using leaf function optimizations in certain cases which is preventing me from being able to do this.
Anyone have any ideas on how to get this to work.
Heap stack trace:
0:013> !heap -p -a 0c060710
address 0c060710 found in
_HEAP # 1420000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0c0606f8 09c3 0000 [00] 0c060710 04e00 - (busy)
77abb234 ntdll!RtlAllocateHeap+0x00000274
75ee404b ole32!CRetailMalloc_Alloc+0x00000016
76454557 OLEAUT32!APP_DATA::AllocCachedMem+0x00000060
7645476a OLEAUT32!SysAllocStringByteLen+0x0000003d
764547bf OLEAUT32!ErrStringCopyNoNull+0x00000016
764547e3 OLEAUT32!VariantCopy+0x0000007f
Break points tried:
bp ntdll!RtlAllocateHeap "j #esi == 0x4e00 ''; 'gc'"
bp ntdll!RtlAllocateHeap "j poi(#ebp-c) == 0x4e00 ''; 'gc'"
bp ntdll!RtlAllocateHeap "j poi(#esp+14) == 0x4e00 ''; 'gc'"
I think I have tested this:
Break on allocation size == 1303
bp ntdll!RtlAllocateHeap "j(poi(#esp+c) = 0x1303) 'k';'gc'"
Use poi(#esp+c)
At the first instruction of the function, you do not have EBP. So the structure on the stack for cdecl and stdcall is
<return address>
<First arg>
<second arg>
etc.