[Dwarf-discuss] Question on loclist
Jun Koi
junkoi2004
Thu Oct 5 14:40:55 GMT 2006
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?
Thank you all for great helps.
Jun
More information about the Dwarf-discuss
mailing list