From: Greg Clayton [mailto:clayborg@gmail.com]
Sent: terça-feira, 19 de setembro de 2017 12:33
To: Leonardo Bianconi <leonardo.bianconi@eldorado.org.br>
Cc: lldb-dev@lists.llvm.org
Subject: Re: [lldb-dev] Reading eValueTypeLoadAddress with missing compiler
type
>
> Some more details:
>
> I'm part of the team that is working in LLDB to enable PPC64le architecture, so
I'm running my test in a Power8 machine.
> When compiling the code with clang, it works, the issue happen when compiling
with gcc, which generates a different debug information content.
>
> Talking a bit about the power stack frame, it is organized this way:
>
> Suppose that you have two functions a() and b() and a calls b, then the frames
will be like this:
>
> high address
> +-----------------+
> > ... | // frame of a
> > ... |
> > ... |
> > ... |
> > ... |
> > back chain | // r31 and r1 points here when running function a
> +-----------------+
> > ... | // frame of b
> >variable address |
> > ... |
> > ... |
> > ... |
> > back chain | // r31 and r1 points here when running function b
> +-----------------+
> low address
>
> The debug information related to find the variable with clang is:
> <2><6ce>: Abbrev Number: 27 (DW_TAG_variable)
> <6cf> DW_AT_location : 3 byte block: 91 f0 0 (DW_OP_fbreg: 112)
> <6d3> DW_AT_name : (indirect string, offset: 0x1cf): a
> <6d7> DW_AT_decl_file : 5
> <6d8> DW_AT_decl_line : 6
> <6d9> DW_AT_type : <0x1bf>
> <2><6dd>: Abbrev Number: 0
> <1><6de>: Abbrev Number: 0
> <1><6b5>: Abbrev Number: 26 (DW_TAG_subprogram)
> <6b6> DW_AT_low_pc : 0x10000630
> <6be> DW_AT_high_pc : 0x88
> <6c2> DW_AT_frame_base : 1 byte block: 6f (DW_OP_reg31 (r31))
> <6c4> DW_AT_name : (indirect string, offset: 0x1ca): main
> <6c8> DW_AT_decl_file : 5
> <6c9> DW_AT_decl_line : 5
> <6ca> DW_AT_type : <0x1bf>
> <6ce> DW_AT_external : 1
>
> Which uses the r31 (DW_OP_reg31) and a positive offset (112) to find it, which
is ok, as it does not need to read the memory using the address in the r31
register.
>
> The issue happen when using the debug information generated by gcc, which
is:
> <2><9e>: Abbrev Number: 5 (DW_TAG_variable)
> <9f> DW_AT_name : a
> <a1> DW_AT_decl_file : 1
> <a2> DW_AT_decl_line : 6
> <a3> DW_AT_type : <0x3b>
> <a7> DW_AT_location : 2 byte block: 91 5c (DW_OP_fbreg: -36)
> <1><81>: Abbrev Number: 4 (DW_TAG_subprogram)
> <82> DW_AT_external : 1
> <82> DW_AT_name : (indirect string, offset: 0xe): main
> <86> DW_AT_decl_file : 1
> <87> DW_AT_decl_line : 5
> <88> DW_AT_type : <0x3b>
> <8c> DW_AT_low_pc : 0x840
> <94> DW_AT_high_pc : 0xf8
> <9c> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
> <9e> DW_AT_GNU_all_tail_call_sites: 1
>
> Here, it says to use the "DW_OP_call_frame_cfa", that is correctly executed in
the LLDB, obtaining the content of r31 and setting it as "
lldb_private::Value::eValueTypeLoadAddress", which means the data it is looking
for is located in the address obtained in the r31, and it need to be read from
memory. If the address was correctly read, it would point to the back chain of the
previous frame, and the variable would be found, as the offset is negative (-36),
so ("previous back chain address" - 36) is the correct variable address.
>
> My code is very simple:
> =====================================
> #include <stdlib.h>
> #include <stdio.h>
>
> int main(void) {
> int a = 2;
> printf("a address: %p \n", (void*)&a);
> printf("a = %d \n", a);
> return 0;
> }
> =====================================
>
> And I'm using the commands:
> gcc -O0 -ggdb stest.cpp (gcc version 5.4.1 20170304)
> clang -O0 -ggdb stest.cpp
>
>
> I think it is not related with the variable type, right?
It might be, can you show the DWARF for the 0x3b type? This was in your GCC
variable's DWARF:
> <a3> DW_AT_type : <0x3b>
It is a 4 byte signed integer:
<1><3b>: Abbrev Number: 3 (DW_TAG_base_type)
<3c> DW_AT_byte_size : 4
<3d> DW_AT_encoding : 5 (signed)
<3e> DW_AT_name : int
There should be nothing wrong with that as long as LLDB is correctly setting r31
into the expression stack in response to the DW_OP_call_frame_cfa opcode. It
should grab r31 - 36 and push the result onto the expression stack with
eValueTypeLoadAddress as the type. Then we just need to read the type from
memory. Since the type is so simple (int), I don't see the type failing here. I am
guessing the DW_OP_call_frame_cfa is messing up the expression somehow.
Can you step through and make sure that "r31 - 36" is correctly being pushed
onto the expression stack?
I think I was not clear when I referenced the " DW_OP_call_frame_cfa", sorry for that. I mean it is trying to resolve the frame base value, not the variable yet, the issue is before trying to get the variable address.
I will do some steps to clarify it:
* Using gcc binary
- On the prompt I type the command "p a" to print the variable value.
- LLDB needs the base frame, which must be found using the debug info " DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)".
- The value of r31 is read, and it is set to " lldb_private::Value::eValueTypeLoadAddress", which means that beyond read the r31 value, this value is an address that must be read as well, in order to point to the previous frame: