Execute a statement while debugging in Rust - debugging

While Coding in Python, I often do something like
test.py
x = []
breakpoint()
± |master U:5 ?:4 ✗| → python3 test.py
-> breakpoint()
(Pdb) x
[]
(Pdb) x.append(1)
(Pdb) x
[1]
Is it possible to execute the statement while debugging Rust?
use std::collections::HashMap;
fn main() {
let mut contacts = HashMap::new();
contacts.insert("Daniel", "798-1364");
contacts.insert("Ashley", "645-7689");
//set breakpoint here
}
So far, I can execute p contacts in the debug console, the meaning of this output isn't straight to me. What if I want to know the outcome of println!("{:?}", contacts); without writting this line of code in the source file.
And also I want to know the outcome of contacts.insert("Robert", "956-1742"), If I execute expr contacts.insert("Robert", "956-1742") in the debug console, it says error: no field named insert.

Rust debugging support is currently quite limited with both lldb and gdb. Simple expressions work, anything more complex is likely to cause problems.
My experience while testing this with rust-lldb:
The expression parser only understands a limited subset of Rust. Macros are not supported.
Functions that are not used are not included in the resulting binary. E.g. you cannot call capacity() on the HashMap in the debugger since that function is not included in the binary.
Methods have to be called like this: struct_value.method(&struct_value)
I haven't found a way to call monomorphized methods on generic structs (like HashMap).
String constants "..." in lldb expressions are created as C-style string constants, e.g. "abcdef" is a const char [7] including the trailing NUL byte. Thus they cannot be easily passed to Rust functions expecting &str arguments.
Trying to use a helper function like this:
pub fn print_contacts(contacts: &HashMap<&str, &str>) {
println!("{:?}", contacts);
}
causes lldb to crash:
(lldb) expr print_contacts(&contacts)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0. Program arguments: [...]
Segmentation fault: 11
So it seems that what you want to do is not possible at this time.

Related

Does CLion possible evaluate a function when debugging Rust code?

A snip of Rust code:
pub fn main() {
let a = "hello";
let b = a.len();
let c =b;
println!("len:{}",c)
}
When debugging in CLion, Is it possible to evaluate a function? For example, debug the code step by step, now the code is running to the last line println!... and the current step stops here, by adding the expression a.len() to the watch a variable window, the IDE can't evaluate the a.len(). It says: error: no field named len
This is the same reason you can't make conditional breakpoints for Rust code:
Can't create a conditional breakpoint in VSCode-LLDB with Rust
I hope, I'm not too late to answer this, but with both lldb and gdb, Rust debugging capability is currently rather constrained.
Expressions that are straightforward work; anything complex is likely to produce issues.
My observations from rust-lldb trying this, are that only a small portion of Rust is understood by the expression parser.
There is no support for macros.
Non-used functions are not included in the final binary.
For instance, since that method is not included in the binary, you are unable to execute capacity() on the HashMap in the debugger.
Methods must be named as follows:
struct value.method(&struct value)
There is no technique that I've discovered to call monomorphized functions on generic structs (like HashMap).
For example, "hello" is a const char [5] including the trailing NUL byte. String constants "..." in lldb expressions are produced as C-style string constants.
Therefore, they are not valid functions

What Rust construct uses nearbyint from libsystem_m?

I've profiled my program with Valgrind and Callgrind and found that most of the time is spent in the nearbyint$fenv_access_off function.
I've found that it's a LLVM intrinsic, but which Rust language construct uses it? How can I avoid it?
Doing a search for nearbyint finds the related symbols nearbyintf32 and nearbyintf64. These are documented as returning the nearest integer to a floating point value. However, there appears to be no calls to that specific function.
fenv_access_off appears to be an OS X specific aspect of the math library.
The other thing in your trace is round. I can believe that round could use nearbyint. I also don't see any cases of round in the standard library that seem like they would occur in a tight loop.
Beyond this, anything is pure guessing.
I've reproduced it with:
fn main() {
let data:Vec<_> = (0..999999).map(|x|{
(x as f64).powf(2.2).round() as u8
}).collect();
}
so it seems as u8 is implemented using nearbyint.
It's the same speed as C uchar = round(pow(i, 2.2)), so I'll have to replace it with a good'ol lookup table…

Why does Xcode/lldb display wrong data?

Why does lldb insist on printing the wrong data — the value of the first ivar, no matter which ivar I ask for? This is Xcode 5.1.1. And yes, I am compiling with -O0, symbols not stripped, etc.
(lldb) print *self
(SMTestHarness) $13 = {
NSObject = {
isa = SMTestHarness
}
_dir = 0x00740520 #"/Users/lc/Projects/servermonitor/Test/unit-test"
_ip = 0x007406b0
_domain = 0x007429f0
_sm = 0x00676900
_state = 0x00741980
_dsaSimulators = 0x00741d10 5 key/value pairs
_timers = 0x00741f50 2 objects
_originalWd = 0x007403f0 #"/Users/lc/Projects/servermonitor/Test"
}
(lldb) print _dir
(NSString *) $14 = 0x00740520 #"/Users/lc/Projects/servermonitor/Test/unit-test"
(lldb) print _ip
(IPAddress *) $15 = 0x00740520
(lldb) print _domain
(FirstPointDomain *) $16 = 0x00740520
(lldb) print _sm
(ServerMonitorCrashTestDummy *) $17 = 0x00740520
Interestingly, the variable display in the left-hand pane is correct; it's only print commands in the lldb console that are wrong.
The variables view in Xcode doesn't use the lldb expression parser (i.e. the print command.) Mainly this is because it would be very inefficient to have to parse expressions for each local variable & its subelements every time you step. And even without this, a full-on expression parser is way more fire power than you need for the task of dumping local variable values.
Instead, lldb has another sub-system just for dumping the contents of variables (no calling functions or complex expressions, just printing values.) From command-line lldb, you can get at that subsystem with the frame variable command.
That bit of trivia probably doesn't help you much, but it is why you can get different results from "print" which runs the fully general expression parser and the Xcode locals view...
What you are seeing, however, is that the lldb expression parser isn't getting the value of the offsets of individual ivars within their containing ObjC object right. The expression parser thinks all the ivars are at 0 offset from the object start - which is in fact what your example shows. And more particularly - from the example you included - this happens when debugging a 32 bit app using the 1.0 version of the Objective C Runtime.
That's a long-standing bug in lldb.
There isn't a good workaround if you have to debug ObjectiveC 1.0 32-bit x86 apps. If you have a 32 bit only machine, then you are pretty much stuck here, and have to use frame var. But if you have a 64-bit capable machine, unless there's some very compelling reason to debug the 32 bit fork of the app, you can just switch to debugging the 64 bit version of the app instead, and this problem should go away.
Note, though the iOS simulator runs 32 bit code, it uses the ObjectiveC 2.0 runtime, and doesn't have this bug.
If you are printing objects use the "po" (print object) command.

lldb: how to call a function from a specific library/framework

Problem: In project we have localization functions which are specific to a framework/dynamic library. That is they have identical name but fetch resources from different bundles/folders
I'd want to call a function from a specific library, something similar to:
lldb> p my_audio_engine.framework::GetL10nString( stringId );
lldb> expr --shlib my_audio_engine.framework -- GetL10nString();
lldb> p my_audio_engine`L10N_Utils::GetString(40000)
but all these variants don't work.
Adding gdb in tags hoping the same semantic if exists will work on lldb as well.
lldb's expression parser doesn't currently have the equivalent of gdb's foo.c::function meta-symbol to encode a function from a specific source file.
Please feel free to file a bug requesting this at bugreporter.apple.com. It will get duped to the one I filed a while ago, but dups are votes for features, and we haven't gotten around to this one yet 'cause nobody but me asked for it...
For the nonce, you will have to do this by hand. Here's a silly example for calling printf, which I happen to know is in libsystem_c.dylib on OS X. First, I find the address in the shared library I am interested in:
(lldb) image lookup -vn printf libsystem_c.dylib
1 match found in /usr/lib/system/libsystem_c.dylib:
Address: libsystem_c.dylib[0x0000000000042948] (libsystem_c.dylib.__TEXT.__text + 266856)
Summary: libsystem_c.dylib`printf
Module: file = "/usr/lib/system/libsystem_c.dylib", arch = "x86_64"
Symbol: id = {0x00000653}, range = [0x00007fff91307948-0x00007fff91307a2c), name="printf"
The first address (the one under Address) is the address of the function in the dylib, not where it got loaded in the running program. That's not immediately useful. I could calculate the library's load offset if I wanted to and apply it to the file address, but fortunately the first address in the Symbol's address range is the address in the running program so I don't have to. 0x00007fff91307948 is the address I want.
Now I want to call that address. I do this in two steps because it makes the casting easier, like:
(lldb) expr typedef int (*$printf_type)(const char *, ...)
(lldb) expr $printf_type $printf_function = ($printf_type) 0x00007fff91307948
Now I have a function I can call over and over:
(lldb) expr $printf_function("Hello world %d times.\n", 400)
Hello world 400 times.
(int) $2 = 23
If you are going to do this over and over, you can write a Python function that finds the symbol out of the library of interest, and constructs the expression that calls the right function. The Python API's include calls to get symbols from a particular module (lldb-speak for loadable binary images), get their addresses, evaluate expressions, etc.

How to print and use constants with gdb (through Xcode)?

I am debugging a Cocoa application using xcode-gdb. I am at a break point and I want view the value of some Cocoa constants (ie NSControlKeyMask) and to do some test with the values in the current stackframe. Specifically I am in - (void) keyDown:(NSEvent *) e , and I have done set $mf = (int)[e modifierFlags] on the gdb prompt. Now I want to do p $mf & NSControlKeyMask and gdb is telling me 'No symbol "NSControlKeyMask" in current context.'
UPDATE:
Xcode has the "Fix and Continue text" feature. So I used Dan M. and n8gray solution with this feature so I don't have to make a proxy of every constant.
If no variables are actually instantiated with a given type, then the debug information for the corresponding symbols doesn't wind up getting generated by gcc. Then, if you ask gdb about such a type, it doesn't know what you are talking about because there is no debug information for that type, and it will give you the "No symbol in current context" error.
A workaround to this problem would normally be to explicitly add a dummy variable, of the type in question, somewhere in the code. Here is a simple example that you can test to see what I'm talking about:
enum an_enum_type {
foo,
bar,
baz
};
int main (int argc, char *argv [])
{
return baz;
}
Save that program to a file named test.cpp and compile it with this command:
g++ -o test -g -O0 test.cpp
Then run it under gdb and type "p /x baz". You will get the "No symbol baz in current context" error.
Now try it with this modified version that has added a dummy variable, of the enum type:
enum an_enum_type {
foo,
bar,
baz
};
an_enum_type dummy;
int main (int argc, char *argv [])
{
return baz;
}
Compile with the same command as before and run under gdb. This time when you type "p /x baz" you'll get "0x2" as the answer, which I think is what you are shooting for in your question.
I've looked into it, and the problem is that the NSEvent.h header file doesn't give a name to the enum that contains NSControlKeyMask -- it's an anonymous enum. So there is no way to create a variable of that type (dummy or otherwise). So, I don't see any way of getting the compiler to generate the debug information for that type. I think you're just going to have to rely on the definition of NSControlKeyMask from the header file.
If you compile with gcc you can use the -g3 switch to get the highest level of debug info. Quoting from the section on -g in the gcc manual:
-glevel
Request debugging information and also use level to specify how much information. The default level is 2.
Level 0 produces no debug information at all. Thus, -g0 negates -g.
Level 1 produces minimal information, enough for making backtraces in parts
of the program that you don't plan to debug. This includes descriptions
of functions and external variables, but no information about local
variables and no line numbers.
Level 3 includes extra information, such as all the macro definitions present
in the program. Some debuggers support macro expansion when you use
-g3.
So if you compile with -g3 you should be able to expand constants and macros in gdb.
As Dan M. discovered, you probably can't get this to work in a straightforward way. Instead, what you could do is put something like this in one of your files:
int myNSControlKeyMask = NSControlKeyMask;
int myNSOptionKeyMask = NSOptionKeyMask;
...
Then at least you can use symbolic names in gdb without having to look up the corresponding values in the .h file.
NSControlKeyMask is most likely a macro and invisible to the debugger. You need to look in the appropriate .h file. Place the cursor over the text NSControlKeyMask in the editor and try command+double-click to jump to its definition.
I seem to be getting the same problem in a bunch of C++ code that is being called from Obj-C in an iPhone app. It's giving me the
No symbol "a" in current context.
error, where a is an int. I tried the -g3 compiler flag with no success. I find it hard to believe gdb doesn't know the type of an int. SDK 3.0, but then again, gdb was printing completely erroneous values when it could find variable in the program.

Resources