[Dwarf-discuss] Question on loclist

Michael Eager eager
Thu Oct 5 15:02:57 GMT 2006


Jun Koi wrote:
> On 10/5/06, Daniel Berlin <dberlin at dberlin.org> wrote:
>>> I compiled kernel with debug info option, and use dwarfdump to extract
>>> information out. Then I got something corresponding to the above code:
>>>
>>> ...
>>>                 DW_AT_name                  do_rmdir
>>>                 DW_AT_decl_file             1 fs/namei.c
>>>                 DW_AT_decl_line             1988
>>>                 DW_AT_prototyped            yes(1)
>>>                 DW_AT_type                  <193>
>>>                 DW_AT_low_pc                0xc01617a0
>>>                 DW_AT_high_pc               0xc0161873
>>>                 DW_AT_frame_base            DW_OP_reg5
>>> <2><41023>      DW_TAG_formal_parameter
>>>                 DW_AT_name                  dfd
>>>                 DW_AT_decl_file             1 fs/namei.c
>>>                 DW_AT_decl_line             1987
>>>                 DW_AT_type                  <49>
>>>                 DW_AT_location              <loclist with 3 entries follows>
>>>                         [ 0]<lowpc=0x2e00><highpc=0x2e19>DW_OP_reg0
>>>                         [ 1]<lowpc=0x2e19><highpc=0x2e3f>DW_OP_reg3
>>>                         [ 2]<lowpc=0x2ec4><highpc=0x2ec7>DW_OP_reg3
>>> <2><41039>      DW_TAG_formal_parameter
>>>                 DW_AT_name                  pathname
>>>                 DW_AT_decl_file             1 fs/namei.c
>>>                 DW_AT_decl_line             1987
>>>                 DW_AT_type                  <64>
>>>                 DW_AT_location              <loclist with 1 entries follows>
>>>                         [ 0]<lowpc=0x2e00><highpc=0x2e19>DW_OP_reg2
>>> <2><41055>      DW_TAG_variable
>>>                 DW_AT_name                  error
>>>                 DW_AT_decl_file             1 fs/namei.c
>>>                 DW_AT_decl_line             1989
>>>                 DW_AT_type                  <49>
>>>                 DW_AT_location              <loclist with 3 entries follows>
>>>                         [ 0]<lowpc=0x2e3b><highpc=0x2e3d>DW_OP_reg0
>>>                         [ 1]<lowpc=0x2e3f><highpc=0x2e53>DW_OP_reg3
>>>                         [ 2]<lowpc=0x2e7a><highpc=0x2ec7>DW_OP_reg3
>>> <2><41071>      DW_TAG_variable
>>>                 DW_AT_name                  name
>>>                 DW_AT_decl_file             1 fs/namei.c
>>>                 DW_AT_decl_line             1990
>>>                 DW_AT_type                  <82>
>>>                 DW_AT_location              <loclist with 2 entries follows>
>>>                         [ 0]<lowpc=0x2e1b><highpc=0x2eca>DW_OP_reg6
>>>                         [ 1]<lowpc=0x2ecf><highpc=0x2ed3>DW_OP_reg6
>>> .....
>>>
>>>
>>> I have few questions:
>>>
>>> 1) Why the location of variable "name" is not made with plain location
>>> expression (like DW_OP_breg5...), but loclist?
>> Because GCC decided to use a location list, and it turned out later it
>> only had one entry.  For various internal reasons, we don't convert it
>> back to a location expression.
>>> 2) Why location of "name" consists of 2 entries?
>> Because the ranges appear disjoint, it could not merge them, since
>> there appears to be a point during the routine where there is no way
>> to validly get the value of name.
>>
>>
>>> "[1]<lowpc=0x2ecf><highpc=0x2ed3>DW_OP_reg6" makes more sense to me,
>>> as the range is exactly 4bytes, and name is in fact a pointer of 4
>>> bytes.
>> The lowpc and highpc are the range of program counters over which the
>> expression is valid, *not* the place in memory where the variable
>> lives.
>>
>>
>>> But how about the 1st entry? What is its meaning?
>> It means that during program execution, when the program counter is
>> between 0x2e1b and 0x2eca, that the variable is in register 6.
>>
>>> 3) Most important question to my project: in the case like above, how
>>> to determine the run-time address of "name"? (Suppose that I can have
>>> value of all the registers - I am on x86)
>> It depends.
>> The absolute simplest way is to store all the location ranges and
>> expression, for the variable in an array:
>>
>> When you want to know the value of the variable
>> 1. get the value of the current PC.
>> 2. Look through the array to see if the PC falls within any of the
>> location ranges.
>>     a. If it does, evaluate the location expression to get the
>> location of the variable
>>     b. If it does not, the value is optimized out
>> 3. Use the location of the variable to read it's value
>>
> 
> Daniel, you are excellent!
> 
> Now I will go through this example again. So in this case, we have:
> 
>                  DW_AT_name                  name
>                  DW_AT_decl_file             1 fs/namei.c
>                  DW_AT_decl_line             1990
>                  DW_AT_type                  <82>
>                  DW_AT_location              <loclist with 2 entries follows>
> ==>                         [ 0]<lowpc=0x2e1b><highpc=0x2eca>DW_OP_reg6
> ==>                         [ 1]<lowpc=0x2ecf><highpc=0x2ed3>DW_OP_reg6
> 
> 
> Because "name" variable belongs to fs/namei.c, the "lowpc" and
> "highpc" mentioned in its loclist are relative to the *base* of the
> *CU*. The CU means the object file, right? So we must look for the CU
> of fs/namei.c. According to dwarfdump output, we have:
> 
> COMPILE_UNIT<header overall offset = 4000707>:
> <0><   11>      DW_TAG_compile_unit
>                 DW_AT_stmt_list             280885
>                 DW_AT_high_pc               0xc0162b62
> ==>         DW_AT_low_pc                0xc015e9a0
>                 DW_AT_producer              GNU C 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
>                 DW_AT_language              DW_LANG_C89
>                 DW_AT_name                  fs/namei.c
>                 DW_AT_comp_dir              /home/jun/linux-2.6.16.29
> 
> I believe the base of the CU is the DW_AT_low_pc. So We must compute
> the range of location for "name", which is 2 ranges:
> 
> (1) { DW_AT_low_pc of CU } + [range 1 of "name" location]
> = 0xC015E9A0 + [<lowpc=0x2e1b> <highpc=0x2eca>]
> 
> (2) { DW_AT_low_pc of CU } + [range2 of "name" location]
> = 0xC015E9A0 + [<lowpc=0x2ecf> <highpc=0x2ed3>]
> 
> Then we check the PC value (ie. EIP) to see if it falls into 1 of the
> above 2 ranges.
> Is that all correct so far?
> 
> Then the final step is to get the location from reg6 (ie.ESI on x86).
> Am I correct in everything?
> 
> 
> 
> 
> OK, if I am right, the final concern is: I am really shocked to see
> these things. Before, I always suppose that the local variable like
> "name" in this example can always be located via stack (ie. EBP). I
> never think that they can be accessed in a different way. But it seems
> it is much more complicated in reality. So why we cannot simplify
> things by using EBP for stuffs on stack?

Gcc will frequently allocate local variables to registers.  There
may not be a stack location reserved for 'name'.  All you know is
that within the specified pc range, the value of name can be found
in reg6.

-- 
Michael Eager	 eager at eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077





More information about the Dwarf-discuss mailing list