[lldb-dev] Reading eValueTypeLoadAddress with missing compiler type

Leonardo Bianconi via lldb-dev lldb-dev at lists.llvm.org
Mon Sep 25 06:25:20 PDT 2017


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.


From: Greg Clayton [mailto:clayborg at gmail.com]
Sent: terça-feira, 19 de setembro de 2017 15:09
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

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.


On Sep 19, 2017, at 10:51 AM, Leonardo Bianconi <leonardo.bianconi at eldorado.org.br<mailto:leonardo.bianconi at eldorado.org.br>> wrote:




-----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<mailto:leonardo.bianconi at eldorado.org.br>>
Cc: lldb-dev at lists.llvm.org<mailto: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<mailto: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<mailto:leonardo.bianconi at eldorado.org.br>>
Cc: lldb-dev at lists.llvm.org<mailto: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<mailto: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<mailto: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<mailto:lldb-dev at lists.llvm.org>
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20170925/0b285a0d/attachment-0001.html>


More information about the lldb-dev mailing list