For what its worth, I compiled the following example

struct stuff {
    union {
        struct {
            int a;
            int b;
        } ints;
        struct {
            char a;
            char b;
        } chars;
    };
};
int main (int argc, char const *argv[], char const *envp[])
{
    stuff s;
    s.ints.a = 11;
    s.ints.b = 22;
    return 0;
}

And it all worked fine:

>>> s = lldb.value(lldb.frame.FindVariable('s'))
>>> print s.ints.b
(int) b = 22
>>> print s.ints.a
(int) a = 11
>>> print s.chars.a
(char) a = '\v'
>>> print s.chars.b
(char) b = '\0'
>>> print hex(s.chars.a)
0xb


What is the type of rvalue? If you can come up with a simple example on what 
isn't working and send it my way I can fix anything that is broken.

Greg


On Apr 17, 2014, at 3:02 PM, Greg Clayton <[email protected]> wrote:

> 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

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

Reply via email to