Reading eValueTypeLoadAddress with missing compiler type

Hi all!

I'm facing an issue with a value of lldb_private::Value::eValueTypeLoadAddress type, which cannot be loaded from memory because the compiler type was not filled.
That happens obtaining the fame base, which is based on "DW_OP_call_frame_cfa" case (DWARFExpression.cpp:2825).
After obtain the base frame, when resolving the value (Value.cpp:612), as the compiler type is invalid, the value is not read from memory, and the frame base keep as its address.

How can I solve this issue?
I looked in many files, and couldn't find how to fill the compiler type in the "DWARFExpression::Evaluate" method.

Thanks,
Leonardo Bianconi.

A DW_TAG_subprogram's usually has a DW_AT_frame_base DWARF expression that describes where the frame is. That evaluates to something and doesn't require any type. I am guessing you now have a variable that is relative to that frame base and that variable's type is not valid. This can be due to many reasons, most likely is the compiler may have redacted your type when trying to save space. Can you confirm this is what is happening?

If you have the binary and the function that this is happening in and can share the binary that contains debug info and also share which file and function and variable is causing the issue, I might be able to tell you why this is happening.

Greg

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

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>

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?

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:

So you need to fix “DW_OP_call_frame_cfa” so it creates the same kind of value on the expression stack as “DW_OP_reg31” does. I am guessing that “DW_OP_reg31” will have a Value that whose value is “eValueTypeScalar”. Verify this and change “DW_OP_call_frame_cfa” to match. We want the Scalar gotten by:

Scalar value;
if (frame->GetFrameBaseValue(value, error_ptr)) {

To be the same kind of value. Seems the expression parsing code that uses “DW_OP_call_frame_cfa” is doing the wrong thing by setting the value to a load address type.

After your e-mail I questioned if that was the right place to fix that, and it wasn’t.

The unwinder was not being created to PPC64le, and it set the CFA with wrong value.

Thanks anyway!

Leonardo Bianconi.