It is either a bug in the lldb.value code (which is in 
LLDB.framework/Resources/Python/lldb/__init__.py) or it could be a bug in LLDB 
where we aren't able to access a variable through an anonymous union.

You might be able to get away with:

rvalue[0].as.basic.flags

Let me know if that works? If it doesn't, you can probably modify the "class 
value" in the "lldb/__init__.py" to "do the right thing. Also when digging up 
child values by name in the []

You might also be able to do: 

  rvalue = page.start[0][0]

then the rvalue should work for you?

If neither do, we can probably fix the name lookup which is currently this:

    def __getattr__(self, name):
        child_sbvalue = self.sbvalue.GetChildMemberWithName (name)
        if child_sbvalue and child_sbvalue.IsValid():
            return value(child_sbvalue)
        raise AttributeError("Attribute '%s' is not defined" % name)

If could be modified to do:


    def __getattr__(self, name):
        child_sbvalue = self.sbvalue.GetChildMemberWithName (name)
        if child_sbvalue and child_sbvalue.IsValid():
            return value(child_sbvalue)
        n = self.sbvalue.GetNumChildren()
        for i in range(n):
            child_sbvalue = self.sbvalue.GetChildAtIndex(i)
            child_name = child_sbvalue.GetName()
            if child_name == None or child_name == '':
                child_value = value(child_sbvalue)
                child_child_sbvalue = child_value.__getattr__(name)
                if child_sbvalue and child_sbvalue.IsValid():
                    return child_value
        raise AttributeError("Attribute '%s' is not defined" % name)


This extra code will check any children that don't have names and recurse down 
into them to find the correct name...

Greg

On Apr 17, 2014, at 2:26 PM, Scott Knight <[email protected]> wrote:

> One last thing I can't seem to figure out. I have this
> 
> self.ruby_current_vm = 
> lldb.value(lldb.target.FindFirstGlobalVariable('ruby_current_vm'))
> self.heaps_used = self.ruby_current_vm.objspace.heap_pages.used
> 
> for i in xrange(self.heaps_used):
>   page = self.ruby_current_vm.objspace.heap_pages.sorted[i]
> 
>   for j in xrange(page.limit):
>     rvalue = page.start[0]
> 
> But I can't seem to access rvalue fields correctly. I would have expected 
> based on the output below that I could do rvalue.as.basic.flags but I get 
> this error
> 
> >>> rvalue.as.basic.flags
>   File "<console>", line 1
>     rvalue.as.basic.flags
>             ^
> SyntaxError: invalid syntax
> 
> Below is the output from printing the whole rvalue variable. It has an 
> anonymous union as. I can do
> 
> real_rvalue = lldb.value(rvalue.__dict__['sbvalue'].GetChildAtIndex[0]) and 
> then I seem to be able to do
> 
> real_rvalue.basic.flags but add that extra line inside the loop above kills 
> the speed and things start getting slower and slower again.
> 
> Thanks,
> Scott Knight
> 
> (RVALUE) [0] = {
>   as = {
>     free = {
>       flags = 98
>       next = 0x00007f9a0107bfa0
>     }
>     basic = (flags = 98, klass = 140299418976160)
>     object = {
>       basic = (flags = 98, klass = 140299418976160)
>       as = {
>         heap = {
>           numiv = 140299418632320
>           ivptr = 0x00007f9a00c274d0
>           iv_index_tbl = 0x00007f9a00c27530
>         }
>         ary = ([0] = 140299418632320, [1] = 140299414435024, [2] = 
> 140299414435120)
>       }
>     }
>     klass = {
>       basic = (flags = 98, klass = 140299418976160)
>       super = 140299418632320
>       ptr = 0x00007f9a00c274d0
>       m_tbl_wrapper = 0x00007f9a00c27530
>     }
>     flonum = {
>       basic = (flags = 98, klass = 140299418976160)
>       float_value = 6.93171228777286E-310
>     }
>     string = {
>       basic = (flags = 98, klass = 140299418976160)
>       as = {
>         heap = {
>           len = 140299418632320
>           ptr = 0x00007f9a00c274d0 ""
>           aux = (capa = 140299414435120, shared = 140299414435120)
>         }
>         ary = "\x80\x80\x02\x01\x9a\x7f"
>       }
>     }
>     array = {
>       basic = (flags = 98, klass = 140299418976160)
>       as = {
>         heap = {
>           len = 140299418632320
>           aux = (capa = 140299414435024, shared = 140299414435024)
>           ptr = 0x00007f9a00c27530
>         }
>         ary = ([0] = 140299418632320, [1] = 140299414435024, [2] = 
> 140299414435120)
>       }
>     }
>     regexp = {
>       basic = (flags = 98, klass = 140299418976160)
>       ptr = 0x00007f9a01028080
>       src = 140299414435024
>       usecnt = 140299414435120
>     }
>     hash = {
>       basic = (flags = 98, klass = 140299418976160)
>       ntbl = 0x00007f9a01028080
>       iter_lev = 12743888
>       ifnone = 140299414435120
>     }
>     data = {
>       basic = (flags = 98, klass = 140299418976160)
>       dmark = 0x00007f9a01028080
>       dfree = 0x00007f9a00c274d0
>       data = 0x00007f9a00c27530
>     }
>     typeddata = {
>       basic = (flags = 98, klass = 140299418976160)
>       type = 0x00007f9a01028080
>       typed_flag = 140299414435024
>       data = 0x00007f9a00c27530
>     }
>     rstruct = {
>       basic = (flags = 98, klass = 140299418976160)
>       as = {
>         heap = {
>           len = 140299418632320
>           ptr = 0x00007f9a00c274d0
>         }
>         ary = ([0] = 140299418632320, [1] = 140299414435024, [2] = 
> 140299414435120)
>       }
>     }
>     bignum = {
>       basic = (flags = 98, klass = 140299418976160)
>       as = {
>         heap = {
>           len = 140299418632320
>           digits = 0x00007f9a00c274d0
>         }
>         ary = ([0] = 16941184, [1] = 32666, [2] = 12743888, [3] = 32666, [4] 
> = 12743984, [5] = 32666)
>       }
>     }
>     file = {
>       basic = (flags = 98, klass = 140299418976160)
>       fptr = 0x00007f9a01028080
>     }
>     node = {
>       flags = 98
>       nd_reserved = 140299418976160
>       u1 = {
>         node = 0x00007f9a01028080
>         id = 140299418632320
>         value = 140299418632320
>         cfunc = 0x00007f9a01028080
>         tbl = 0x00007f9a01028080
>       }
>       u2 = {
>         node = 0x00007f9a00c274d0
>         id = 140299414435024
>         argc = 140299414435024
>         value = 140299414435024
>       }
>       u3 = {
>         node = 0x00007f9a00c27530
>         id = 140299414435120
>         state = 140299414435120
>         entry = 0x00007f9a00c27530
>         args = 0x00007f9a00c27530
>         cnt = 140299414435120
>         value = 140299414435120
>       }
>     }
>     match = {
>       basic = (flags = 98, klass = 140299418976160)
>       str = 140299418632320
>       rmatch = 0x00007f9a00c274d0
>       regexp = 140299414435120
>     }
>     rational = {
>       basic = (flags = 98, klass = 140299418976160)
>       num = 140299418632320
>       den = 140299414435024
>     }
>     complex = {
>       basic = (flags = 98, klass = 140299418976160)
>       real = 140299418632320
>       imag = 140299414435024
>     }
>     values = {
>       basic = (flags = 98, klass = 140299418976160)
>       v1 = 140299418632320
>       v2 = 140299414435024
>       v3 = 140299414435120
>     }
>   }
> }
> 
> 
> On Thu, Apr 17, 2014 at 2:27 PM, Greg Clayton <[email protected]> wrote:
> 
> 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