[lldb-dev] Reading eValueTypeLoadAddress with missing compiler type

Leonardo Bianconi via lldb-dev lldb-dev at lists.llvm.org
Tue Sep 19 10:51:58 PDT 2017



> -----Original Message-----
> From: Greg Clayton [mailto:clayborg at gmail.com]
> Sent: terça-feira, 19 de setembro de 2017 12:33
> To: Leonardo Bianconi <leonardo.bianconi at eldorado.org.br>
> Cc: lldb-dev at lists.llvm.org
> Subject: Re: [lldb-dev] Reading eValueTypeLoadAddress with missing compiler
> type
> 
> 
> > On Sep 19, 2017, at 4:10 AM, Leonardo Bianconi
> <leonardo.bianconi at eldorado.org.br> wrote:
> >
> > 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:

+-----------+
|           | // frame of a
|back chain | //previous r31' and r1'
+-----------+
|           | // frame of b
|back chain | //current r31 and r1
+-----------+

Issue: It should get the r31' as address of frame base to apply the offset, and read the variable value that is inside the "frame of b", as the offset is negative. Instead of that, as the compiler type is invalid, the address obtained from r31 value is not being read, no error is shown, and the frame base value keeps as r31, which is incorrect. When using this value, the variable address is located in the red zone "r31 - 28 (offset)" (DW_AT_location    : 2 byte block: 91 64      (DW_OP_fbreg: -28)).


* Using Clang 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: 6f        (DW_OP_reg31 (r31))".
- The value of r31 is read, and the memory of the address found in r31 is not read from memory, when running the case " DW_OP_reg31".

+-----------+
|           | // frame of a
|back chain | //previous r31' and r1'
+-----------+
|           | // frame of b
|back chain | //current r31 and r1
+-----------+

Result: It gets the r31 value, which points to the back chain of the "frame b", as expected, because the offset is positive, so "r31 + 112" (<6cf>   DW_AT_location    : 3 byte block: 91 f0 0   (DW_OP_fbreg: 112)).



It is visible that gcc and lldb generates different debug info, gcc calculates the variable offset from the beginning of the frame, while lldb from the end of the frame. I saw in the code that LLDB is getting the correct information about the frame, but as the compiler type is invalid, the memory is not read, if it was valid, it would work correctly, that is why I'm trying to set the correct compiler type. I need to know what compiler type to use when reading the previous frame.

I placed the full output from the binaries in the pastbin:
Clang debug info: https://pastebin.com/tyXp5C9g
Gcc debug info: https://pastebin.com/00b0SiKm
Disassembly of gcc binary: https://pastebin.com/06UakF24 


> 
> >
> > Thanks!
> >
> >
> >
> >> -----Original Message-----
> >> From: Greg Clayton [mailto:clayborg at gmail.com]
> >> Sent: segunda-feira, 18 de setembro de 2017 17:24
> >> To: Leonardo Bianconi <leonardo.bianconi at eldorado.org.br>
> >> Cc: lldb-dev at lists.llvm.org
> >> Subject: Re: [lldb-dev] Reading eValueTypeLoadAddress with missing compiler
> >> type
> >>
> >> 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
> >>
> >>> On Sep 18, 2017, at 1:23 PM, Greg Clayton <clayborg at gmail.com> wrote:
> >>>
> >>> 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?
> >>>
> >>>
> >>>> On Sep 18, 2017, at 12:25 PM, Leonardo Bianconi via lldb-dev <lldb-
> >> dev at lists.llvm.org> wrote:
> >>>>
> >>>> 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.
> >>>> _______________________________________________
> >>>> lldb-dev mailing list
> >>>> lldb-dev at lists.llvm.org
> >>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> >>>
> >



More information about the lldb-dev mailing list