[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