Given a file name, line number and variable name, I am trying to determine the address. I tried the following approach:
· First I got the block corresponding to the file and line:
o from the file name I got a SBCompileUnit
o using the SBCompileUnit and line number I got a SBLineEntry
§ for FindLineEntryIndex the “exact” parameter needs to be false else it will return empty if the line is on a function
o get the SBBlock: lineEntry.GetStartAddress().GetBlock()
· Now I got the variables for that block and search by name
Any easier way might be to set a breakpoint by file and line. There may be more than one breakpoint location for a given file and line (inline functions for example). Once you have a breakpoint you can check the SBAddress of each location:
lldb::SBBreakpoint bp = target.BreakpointCreateByLocation("main.cpp", 12);
const size_t num_locs = bp.GetNumLocations();
for (size_t i=0; i<num_locs; ++i)
lldb::SBBreakpointLocation bp_loc = bp.GetLocationAtIndex(i);
lldb::SBSymbolContext sc = bp.GetSymbolContext(lldb::eSymbolContextEverything);
// Now you have a symbol context that can give you all info
lldb::SBFunction function = sc.GetFunction();
lldb::SBBlock block = sc.GetBlock();
lldb::SBLineEntry line_entry = sc.GetLineEntry();
o block.GetVariables(target, True, True, True)
o I still need to figure out if on the given line there is a function static and a function argument since both will show up in the list
You can ask each SBValue for its lldb::ValueType:
eValueTypeInvalid = 0,
eValueTypeVariableGlobal = 1, // globals variable
eValueTypeVariableStatic = 2, // static variable
eValueTypeVariableArgument = 3, // function argument variables
eValueTypeVariableLocal = 4, // function local variables
eValueTypeRegister = 5, // stack frame register value
eValueTypeRegisterSet = 6, // A collection of stack frame register values
eValueTypeConstResult = 7 // constant result variables
o Search for the variable by name and get its address – there is no address L
You can ask each value for its load address with:
You must be stopped in a stack frame in order for this to work with locals and arguments. Statics and globals will be able to answer the question _if_ the module that contains the static/global is loaded into memory in a process that is running. You can also set make a target and manually set the load locations of shared libraries (see http://lldb.llvm.org/symbolication.html) and then you will be able to get addresses for globals/statics.
The problem is that for line 3 in the code below, my SBValue object in the list doesn’t have an address, just “<Invalid stack frame in context for DW_OP_fbreg opcode.>”. Any ideas how to solve this?
You can't evaluate expressions for local variables unless you are in the stack frame stopped at that address. Why? Variables say "I am located at the frame base pointer + 32". So unless you actually are stopped in a stack frame at that address, you won't be able to know what "frame base pointer" is. This is typically the RBP register on x86_64, EBP on x86, and FP register on ARM and ARM64.
Also, how can I set the context for evaluating an expression to a file and line number? (on line 8, evaluate “v” to 1)
Again, you really can't set the context because you actually need to be stopped there so that the CPU registers are all setup and correct. You can just set breakpoints and run to the needed locations and then evaluate the expressions when you know where you are stopped so that you know which expressions you will want to evaluate.
There are two ways to evaluate an expression:
- use a lldb::SBTarget
- use a lldb::SBFrame
If you use the target, you can evaluate an expression for code like:
int g_global = 123;
lldb::SBValue global_expr = target.EvaluateExpression("g_global");
Since "g_global" has a value in the .data section, it can be evaluated without needing a frame and this expression will after you create your target and before you actually run it because it can read the value of g_global from the .data section in your executable.
If you use a stack frame, then you are stopped somewhere and are asking the frame to help evaluate the values of any local and arguments values for the current function.
Does that make more sense?