[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