SBValue
SBTarget::FindFirstGlobalVariable (const char* name);

This doesn't support the "GetValueForVariablePath()", so you will need to do:

ruby_current_vm = lldb.target.FindFirstGlobalVariable('ruby_current_vm');

heaps_used = 
ruby_current_vm.GetValueForExpressionPath('->objspace->heap_pages.used').GetValueAsUnsigned(0)

You can also use a very handy wrapper utility class called lldb.value:

ruby_current_vm = 
lldb.value(lldb.target.FindFirstGlobalVariable('ruby_current_vm'))

Now "ruby_current_vm" behaves like a C structure would, except you can't use 
"->" to refer to a child of a pointer you need to use ".". So you should be 
able to do:

heaps_used = ruby_current_vm.objspace.heap_pages.used

for i in xrange(heaps_used):
    page = ruby_current_vm.objspace.heap_pages.sorted[i]

You had a derefernce on "page" before, but, you can use page is a lldb.value, 
so you can just do "page.foo.bar" if you need anything inside of it.

Greg

On Apr 17, 2014, at 11:09 AM, Scott Knight <[email protected]> wrote:

> Thanks for the information Greg. I have a quick followup. I'm using the 
> version of lldb that comes with XCode 5.1.1
> 
> Launching it like this
> 
> Scotts-MacBook-Pro:~ scottknight$ 
> /Applications/Xcode.app/Contents/Developer/usr/bin/lldb -p 13892
> Attaching to process with:
>     process attach -p 13892
> Process 13892 stopped
> Executable module set to "/Users/scottknight/.rbenv/versions/2.1.1/bin/ruby".
> Architecture set to: x86_64-apple-macosx.
> 
> When I tried using GetValueForVariablePath I got 'No value' back. See the 
> output below.
> 
> (lldb) v
> lldb-310.2.37
> (lldb) script
> Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
> >>> print lldb.frame.EvaluateExpression('ruby_current_vm')
> (rb_vm_t *) $1 = 0x00007f9a01003000
> >>> print lldb.frame.GetValueForVariablePath('ruby_current_vm')
> No value
> 
> Since ruby_current_vm is a global variable is there something different I 
> would need to do to access it?
> 
> Thanks,
> Scott Knight
> 
> 
> On Thu, Apr 17, 2014 at 1:45 PM, Greg Clayton <[email protected]> wrote:
> Running expressions has all sorts of side effects like storing data in the 
> inferior program and it also involves running the clang expression parser 
> which can be expensive.
> 
> You can, from a frame, get a SBValue for a variable without using the 
> expression parser:
> 
>     lldb::SBValue
>     SBFrame.GetValueForVariablePath (const char *var_path);
> 
> So you can change your code to this:
> 
> heaps_used = 
> lldb.frame.GetValueForVariablePath('ruby_current_vm->objspace->heap_pages.used').GetValueAsUnsigned(0)
> 
> for i in xrange(heaps_used):
>     page = 
> lldb.frame.GetValueForVariablePath('*ruby_current_vm->objspace->heap_pages.sorted[%i]'
>  % i)
> 
> The GetValueForVariablePath() will find the variable and not create a 
> temporary each time. It also doesn't use the expression parser at all so it 
> won't call any code. The objects you access must be available in the 
> hierarchy of the struct or class and the struct or class can't override the 
> "->" operator. Other than that, the GetValueForVariablePath() knows how to 
> access members ("ruby_current_vm->objspace->heap_pages.sorted"), dereference 
> pointers using the array syntax ("my_ptr[12]"), deref a pointer 
> ("*this->other_ptr"), and take the address of something 
> ("&ruby_current_vm->objspace->heap_pages.sorted[12]").
> 
> So give the GetValueForVariablePath a try. The SBValue returned is something 
> that represents the live variable value, not a const result like you get back 
> from expression. SBValue you get back is tied to the frame from which you got 
> it, so it will continue to evaluate correctly and its value will change if 
> you step between calling functions with it. If the frame it came from goes 
> away (step out), then it won't return any valid values again as it will 
> detect the frame is gone and stop answering any questions. So you should 
> always fetch a fresh value from the frame each time you want to use it.
> 
> Greg
> 
> 
> On Apr 17, 2014, at 7:57 AM, Scott Knight <[email protected]> wrote:
> 
> > I was recently using lldb to connect to a debug build of ruby to inspect 
> > the heap. In order to do this I was doing something like this
> >
> > -----------
> > heaps_used = 
> > lldb.frame.EvaluateExpression('ruby_current_vm->objspace->heap_pages.used').GetValueAsUnsigned(0)
> >
> > for i in xrange(heaps_used):
> >     page = 
> > lldb.frame.EvaluateExpression('*ruby_current_vm->objspace->heap_pages.sorted[%i]'
> >  % i)
> > -----------
> >
> > What I noticed was that for each EvaluateExpression a temporary $0, $1, $2, 
> > etc.. variable is created. If I ended up calling my python code multiple 
> > times more and more variables seemed to pile up and every 
> > EvaluateExpression call seemed to take longer and longer.
> >
> > I tried calling EvaluateExpression how I would call expr from the lldb 
> > command line setting my own variable, so something like
> >
> > lldb.frame.EvaluateExpression('int $test = 5')
> >
> > But that seemed to error out. So is there some other way in the API that is 
> > better for accessing global variables that won't slow down. Is this 
> > something actually wrong with the debugger? I can create an actual test 
> > case similar to the test suite in lldb if that would be helpful.
> >
> > Thanks,
> > Scott Knight
> >
> > _______________________________________________
> > lldb-dev mailing list
> > [email protected]
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> 
> 

_______________________________________________
lldb-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to