3 Commits

Author SHA1 Message Date
nerix
3c162ba247
[LLDB][NativePDB] Add non-overlapping fields in root struct (#166243)
When anonymous unions are used in a struct or vice versa, their fields
are merged into the parent record when using PDB. LLDB tries to recreate
the original definition of the record _with_ the anonymous
unions/structs.

For tagged unions (like `std::optional`) where the tag followed the
anonymous union, the result was suboptimal:

```cpp
// input:
struct Foo {
  union {
    Bar b;
    char c;
  };
  bool tag;
};

// reconstructed:
struct Foo {
  union {
    Bar b;
    struct {
      char c;
      bool tag;
    };
  };
};
```

Once the algorithm is in some nested union, it can't get out.

In the above case, we can get to the correct reconstructed record if we
always add fields that don't overlap others in the root struct. So when
we see `tag`, we'll see that it comes after all other fields, so it's
possible to add it in the root `Foo`.
2025-11-05 19:07:44 +01:00
Jonas Devlieghere
cf3464bbb7
[lldb] Set LLDB_USE_NATIVE_PDB_READER at the directory level (#114455)
Lit allows you to set environment variables for all tests in a directory
using a `lit.local.cfg` file. Do this for the PDB and NativePDB tests.
2024-10-31 15:31:51 -07:00
Zequan Wu
d3492ed016 [LLDB][NativePDB] Fix struct layout when it has anonymous unions.
Previously, lldb mistook fields in anonymous union in a struct as the direct
field of the struct, which causes lldb crashes due to multiple fields sharing
the same offset in a struct. This patch fixes it.

MSVC generated pdb doesn't have the debug info entity representing a anonymous
union in a struct. It looks like the following:
```
struct S {
union {
  char c;
  int i;
};
};

0x1004 | LF_FIELDLIST [size = 40]
         - LF_MEMBER [name = `c`, Type = 0x0070 (char), offset = 0, attrs = public]
         - LF_MEMBER [name = `i`, Type = 0x0074 (int), offset = 0, attrs = public]
0x1005 | LF_STRUCTURE [size = 32] `S`
         unique name: `.?AUS@@`
         vtable: <no type>, base list: <no type>, field list: 0x1004
```
Clang generated pdb is similar, though due to the [[ https://github.com/llvm/llvm-project/issues/57999 | bug ]],
it's not more useful than the debug info above. But that's not very relavent,
lldb should still be able to understand MSVC geneerated pdb.
```
0x1003 | LF_UNION [size = 60] `S::<unnamed-tag>`
         unique name: `.?AT<unnamed-type-$S1>@S@@`
         field list: <no type>
         options: forward ref (= 0x1003) | has unique name | is nested, sizeof 0
0x1004 | LF_FIELDLIST [size = 40]
         - LF_MEMBER [name = `c`, Type = 0x0070 (char), offset = 0, attrs = public]
         - LF_MEMBER [name = `i`, Type = 0x0074 (int), offset = 0, attrs = public]
         - LF_NESTTYPE [name = ``, parent = 0x1003]
0x1005 | LF_STRUCTURE [size = 32] `S`
         unique name: `.?AUS@@`
         vtable: <no type>, base list: <no type>, field list: 0x1004
         options: contains nested class | has unique name, sizeof 4
0x1006 | LF_FIELDLIST [size = 28]
         - LF_MEMBER [name = `c`, Type = 0x0070 (char), offset = 0, attrs = public]
         - LF_MEMBER [name = `i`, Type = 0x0074 (int), offset = 0, attrs = public]
0x1007 | LF_UNION [size = 60] `S::<unnamed-tag>`
         unique name: `.?AT<unnamed-type-$S1>@S@@`
         field list: 0x1006
         options: has unique name | is nested | sealed, sizeof
```
This patch delays the FieldDecl creation when travesing LF_FIELDLIST so we know
if there are multiple fields are in the same offsets and are able to group them
into different anonymous unions based on offsets. Nested anonymous union will
be flatten into one anonymous union, because we simply don't have that info, but
they are equivalent in terms of union layout.

Differential Revision: https://reviews.llvm.org/D134849
2022-10-13 12:43:45 -07:00