To debug the values of high frequency timers or sensors it would be useful to configure a breakpoint that only fires every x times. What's the best way to accomplish this?
I tried the "Ignore x times before stopping" option in Xcode but that only works for the first time. Can I reset this counter using an LLDB command?
You can reset the ignore counter at any time with:
(lldb) break modify -i <NEW_VALUE> <BKPT_SPECIFICATION>
Note, a breakpoint which doesn't satisfy its "ignore count" is not considered to be hit, so its breakpoint command does NOT get run. So if you wanted to stop every tenth the time you hit the breakpoint automatically, just do:
(lldb) break set -l 10 -i 10 -N my_bkpt
Breakpoint 1: where = foo`main + 46 at foo.c:10, address = 0x0000000100000f5e
(lldb) break com add
Enter your debugger command(s). Type 'DONE' to end.
> break modify -i 10 my_bkpt
> DONE
(lldb)
Then just hit "continue" at each stop and you will hit the breakpoint once every 10 times.
Note, I used the ability to name the breakpoint (the -N option) so I didn't have to know the breakpoint number in the breakpoint command that I added. That's convenient if you're going to store these breakpoints in a command file, etc.
Ref: Apple docs on Managing breakpoints. You can also do help breakpoint set command for a complete list of available options
I'm not sure you can define a persistent variable(counter) in lldb. You can always have one global var that you use as a counter helper and simply not include it in the release builds.
class BrCounter{
static var freq = 10
}
Edit the breakpoint and add the following condition:
BrCounter.freq--;
if(BrCounter.freq == 0){
BrCounter.freq = 10;
return true;
}else{
return false;
}
Oneliner:
BrCounter.freq--; if(BrCounter.freq == 0){ BrCounter.freq = 10; return true; }else{ return false; }
Related
The code which need to be executed when Button is clicked. It is being executed twice.
when I use "if(this == 1)" I am having an error "Operand types are incompatible"
on sysvar_update sysvar::NexteerData::WriteRead
{
seclevel = 1;
ExtendedSession.SendRequest();
toggle2 = 1;
Write("Write CALIBRATION VALUES");
}
When using the value of the system variable in an if statement, use as follows:
if(#this == 1)
This will solve your error and also the double execution issue.
I'm trying to write a DTrace script which does the following:
Whenever a new thread is started, increment a count.
Whenever one of these threads exits, decrement the count, and exit the script if the count is now zero.
I have something like this:
BEGIN {
threads_alive = 0;
}
proc:::lwp-start /execname == $$1/ {
self->started = timestamp;
threads_alive += 1;
}
proc:::lwp-exit /self->started/ {
threads_alive -= 1;
if (threads_alive == 0) {
exit(0);
}
}
However, this doesn't work, because threads_alive is a scalar variable and thus it is not multi-cpu safe. As a result, multiple threads will overwrite each other's changes to the variable.
I have also tried using an aggregate variable instead:
#thread_count = sum(1)
//or
#threads_entered = count();
#threads_exitted = count();
Unfortunately, I haven't found syntax to be able to do something like #thread_count == 0 or #threads_started == #threads_stopped.
DTrace doesn't have facilities for doing the kind of thread-safe data sharing you're proposing, but you have a few options depending on precisely what you're trying to do.
If the executable name is unique, you can use the proc:::start and proc:::exit probes for the start of the first thread and the exit of the last thread respectively:
proc:::start
/execname == $$1/
{
my_pid = pid;
}
proc:::exit
/pid == my_pid/
{
exit(0);
}
If you're using the -c option to dtrace, the BEGIN probe fires very shortly after the corresponding proc:::start. Internally, dtrace -c starts the specified forks the specified command and then starts tracing at one of four points: exec (before the first instruction of the new program), preinit (after ld has loaded all libraries), postinit (after each library's _init has run), or main (right before the first instruction of the program's main function, though this is not supported in macOS).
If you use dtrace -x evaltime=exec -c <program> BEGIN will fire right before the first instruction of the program executes:
# dtrace -xevaltime=exec -c /usr/bin/true -n 'BEGIN{ts = timestamp}' -n 'pid$target:::entry{printf("%dus", (timestamp - ts)/1000); exit(0); }'
dtrace: description 'BEGIN' matched 1 probe
dtrace: description 'pid$target:::entry' matched 1767 probes
dtrace: pid 1848 has exited
CPU ID FUNCTION:NAME
10 16757 _dyld_start:entry 285us
The 285us is due to the time it takes dtrace to resume the process via /proc or ptrace(2) on macOS. Rather than proc:::start or proc:::lwp-start you may be able to use BEGIN, pid$target::_dyld_start:entry, or pid$target::main:entry.
In a tcl/tk dialog I need to get a text input from the user.
proc add_entry { command } {
global TestValue
entry .dialog_TC.enText -textvariable TestValue
grid .dialog_TC.enText -row 1 -column 1 -columnspan 2 -pady 1 -padx 1
}
The problem:
Whenever the user writes a single letter, into the entry-field, the dialog is closed immediately.
I'm guessing that you've got a trace elsewhere on the TestValue variable (possibly due to vwait or tkwait variable) that is detecting the change to the variable and destroying the widget when that happens, possibly by killing the whole dialog. You don't include the code, but it's probably something like:
proc make-me-a-dialog {} {
toplevel .dialog_TC
# ...
add_entry { something ... }
# ...
vwait TestValue
destroy .dialog_TC
return $TestValue
}
That's a guess, and probably greatly simplified too. But if that's the case, the first event to change the value in the variable (i.e., most key-presses in the entry) will cause the vwait to stop waiting and trigger the cascade of destruction.
You need to stop waiting on the contents of the entry. You don't want to trigger every time something is altered in it, but rather only when the user says “I'm done and want to make my changes, OK” or “I'm done and don't want to make my changes, Cancel”. Or, depending on interaction style, “I'm done; my changes are already live. Close this window”. With plenty of experience, the events that you are actually needing to listen for are the closing of the window, the press of Return and the press of Escape.
Let's fix.
proc make-me-a-dialog {}
global waiting
toplevel .dialog_TC
# ...
add_entry { something ... }
# ...
set dlg .dialog_TC
bind $dlg <Return> [list set waiting($dlg) 1]
bind $dlg <Escape> [list set waiting($dlg) 0]
# Trapping a window manager message; slightly different to normal events for historical reasons
wm protocol $dlg WM_DELETE_WINDOW [list set waiting($dlg) 0]
vwait waiting($dlg)
if {waiting($dlg)} {
return $ValueIndicatingOK
} else {
return $ValueIndicatingCancel
}
}
Ok, I did not think about my shortkeys, that I have also in that script. Whenever one of those letters is written into the entry field the window gets closed. I have to combine keys like ...
bind . <Control-Key-a> \
{ tk_messageBox -message "You pressed Control+A" } ;#Control+a
Given a positive number N, my print_even() function prints out all the even numbers between 1 and N:
-module(my).
-compile(export_all).
print_even(N) when N>0 -> even_helper(1, N).
even_helper(Current, N) when Current =< N ->
io:format("(Current = ~w)~n", [Current]),
case Current rem 2 of
0 -> io:format("Number: ~p~n", [Current]);
_ -> do_nothing
end,
even_helper(Current+1, N);
even_helper(Current, N) when Current > N ->
ok.
Here's some sample output:
28> my:print_even(10).
(Current = 1)
(Current = 2)
Number: 2
(Current = 3)
(Current = 4)
Number: 4
(Current = 5)
(Current = 6)
Number: 6
(Current = 7)
(Current = 8)
Number: 8
(Current = 9)
(Current = 10)
Number: 10
ok
Below is the code I'm using for a conditional break:
-module(c_test).
-compile(export_all).
c_break(Bindings) ->
case int:get_bindings('Current', Bindings) of
{value, 3} -> true;
_ -> false
end.
I set a conditional break on the following line in print_even():
case Current rem 2 of
...which according to the Erlang debugger docs should be legal. But no matter what I do, I can't get my c_break() function to execute. I expected execution to halt at the breakpoint when Current is equal to 3, but the code runs to completion, and the breakpoint is skipped. I even tried:
c_break(Bindings) ->
case int:get_bindings('Current', Bindings) of
_ -> true;
end.
But execution still won't halt at the breakpoint.
Update: I can get execution to halt if I use the following function for my conditional break:
c_break(_) ->
true.
If I change that to:
c_break(X) ->
io:format("~w~n", [X]),
true.
...then once again execution won't halt.
!##$!##$#!! It should be:
int:get_binding()
^
|
not:
int:get_bindings()
^
|
Even then, recompiling the module did not succeed in getting execution to halt. To get things to work, I had to quit the debugger: I closed all the debugger windows, then I issued the command:
82> debugger:stop().
ok
(I can't find any information for the function debugger:stop(), so I don't know if that is necessary or even does anything.)
Then I recompiled both modules:
83> c(my, [debug_info]).
{ok,my}
84> c(c_test).
{ok,c_test}
Then:
85> debugger:start().
{ok,<0.305.0>}
debugger:start() launches the Monitor window, and with the Monitor window active I chose the menu item:
Module > Interpret
...and I selected my.erl from the popup--where my.erl is the module containing the function where I want to halt execution.
Then with the Monitor window still active, I chose the menu item:
Break>Conditional Break
...and I filled in the information. You can also double click your module name displayed in the Monitor window, and then use the View Module window that opens to set breakpoints. The View Module window displays your source code, and the window also has a Break menu item, which allows you to set the various types of breakpoints. In the View Module window, you can use a shortcut for creating a Line breakpoint, i.e. a regular breakpoint: you can set a breakpoint by double clicking a line in your code.
Finally:
86> my:print_even(10).
(Current = 1)
(Current = 2)
Number: 2
(Current = 3)
Hurray!
Then I double clicked on the process listed in the Monitor window, and an Attach Process window opened. The Attach Process window shows where execution halted in your code, and it provides the means for you to step through the code.
Back in the Monitor window, if you check the checkbox On Break, then an Attach Process window will open automatically when execution halts at a breakpoint. As far as I can tell, you need to open a new Attach Process window every time you run your code.
By the way, the module name c_test and the function name c_break() can be any name. Their names are not important, for instance I changed the module name to conditional_breaks and the function name to break1().
The problem:
I've got a situation where we have a media playback during launch, and objc_exception_throw() hits about 5 times during that period, but is always caught, and it's way south of the media player object.
I'm tired of either (a) having to manually continue n times, or (b) having to leave breakpoints disabled until after the playback is complete.
What I've tried:
making the breakpoint ignore the first five hits (problem: it's not always exactly five times)
creating my own symbolic breakpoint using my target as the module (problem: nothing changed)
What I'd like to do:
One solution that comes to mind is to evaluate the stack when the breakpoint hits, and continue if a particular method or function is listed therein. But I have no idea how to do this.
Other ideas welcome as well.
You do it using Python.
The following defines an ignore list and a function you can attach as a command to a breakpoint.
The function grabs the names of functions in the backtrace and set-intersects those names with the ignore list. If any names match, it continues running the process. This effectively skips dropping into the debugger for unwanted stacks.
(lldb) b objc_exception_throw
Breakpoint 1: where = libobjc.A.dylib`objc_exception_throw, address = 0x00000000000113c5
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> ignored_functions = ['recurse_then_throw_and_catch']
def continue_ignored(frame, bp_loc, dict):
global ignored_functions
names = set([frame.GetFunctionName() for frame in frame.GetThread()])
all_ignored = set(ignored_functions)
ignored_here = all_ignored.intersection(names)
if len(ignored_here) > 0:
frame.GetThread().GetProcess().Continue()
quit()
(lldb) br comm add -F continue_ignored 1
(lldb) r
I tried it against the following file, and it successfully skips the first throw inside recurse_then_throw_and_catch and drops into the debugger during the throw inside throw_for_real.
#import <Foundation/Foundation.h>
void
f(int n)
{
if (n <= 0) #throw [NSException exceptionWithName:#"plugh" reason:#"foo" userInfo:nil];
f(n - 1);
}
void
recurse_then_throw_and_catch(void)
{
#try {
f(5);
} #catch (NSException *e) {
NSLog(#"Don't care: %#", e);
}
}
void
throw_for_real(void)
{
f(2);
}
int
main(void)
{
recurse_then_throw_and_catch();
throw_for_real();
}
I imagine you could add this function to your .lldbinit and then connect it to breakpoints as needed from the console. (I don't think you can set a script command from within Xcode.)
break command add -s python -o "return any('xyz' in f.name for f in frame.thread)"
If a python breakpoint command returns False, lldb will keep going. So this is saying: if any frame in the stack has the string 'xyz' in its name, then return True (to stop). Otherwise if no frame has that name, this any expression will return False (to keep going).