This patch extracts the logic to create a static variable member decl
into a helper. We will use this in an upcoming patch which will need to
call exactly the same logic from a separate part of the DWARF parser.
Changed the recently added `FindConstantOnVariableDefinition` to
not rely on MemberAttributes being non-const.
Original commit message:
"""
This patch removes the Objective-C accessibility workaround added in
5a477cfd90
(rdar://8492646). This allows us to make the local `MemberAttributes`
variable immutable, which is useful for some other work around this
function I was planning on doing.
We don't need the workaround anymore since compiler-support for giving
debuggers access to private ivars was done couple of years later in
d6cb4a858d
(rdar://10997647).
**Testing**
* Test-suite runs cleanly
"""
This patch removes the Objective-C accessibility workaround added in
5a477cfd90
(rdar://8492646). This allows us to make the local `MemberAttributes`
variable immutable, which is useful for some other work around this
function I was planning on doing.
We don't need the workaround anymore since compiler-support for giving
debuggers access to private ivars was done couple of years later in
d6cb4a858d
(rdar://10997647).
**Testing**
* Test-suite runs cleanly
This patch relands https://github.com/llvm/llvm-project/pull/71004 which
was reverted because the clang change it depends on was reverted.
In addition to the original patch, this PR includes a change to
`SymbolFileDWARF::ParseVariableDIE` to support CU-level variable
definitions that don't have locations, but represent a constant value.
Previously, when debug-maps were available, we would assume that a
variable with "static lifetime" (which in this case means "has a linkage
name") has a valid address, which isn't the case for non-locationed
constants. We could omit this additional change if we stopped attaching
linkage names to global non-locationed constants.
Original commit message:
"""
https://github.com/llvm/llvm-project/pull/71780 proposes moving the
`DW_AT_const_value` on inline static members from the declaration DIE to
the definition DIE. This patch makes sure the LLDB's expression
evaluator can continue to support static initialisers even if the
declaration doesn't have a `DW_AT_const_value` anymore.
Previously the expression evaluator would find the constant for a
VarDecl from its declaration `DW_TAG_member` DIE. In cases where the
initialiser was specified out-of-class, LLDB could find it during symbol
resolution.
However, neither of those will work for constants, since we don't have a
constant attribute on the declaration anymore and we don't have
constants in the symbol table.
"""
Depends on:
* https://github.com/llvm/llvm-project/pull/71780
This casued asserts:
llvm/lib/IR/Metadata.cpp:689:
void llvm::MDNode::resolve(): Assertion `isUniqued() && "Expected this to be uniqued"' failed.
See comments on the PR.
This also reverts the dependent follow-up commits, see below.
> When an LLDB user asks for the value of a static data member, LLDB
> starts by searching the Names accelerator table for the corresponding
> variable definition DIE. For static data members with out-of-class
> definitions that works fine, because those get represented as global
> variables with a location and making them eligible to be added to the
> Names table. However, in-class definitions won<E2><80><99>t get indexed because
> we usually don't emit global variables for them. So in DWARF we end
> up with a single `DW_TAG_member` that usually holds the constant
> initializer. But we don't get a corresponding CU-level
> `DW_TAG_variable` like we do for out-of-class definitions.
>
> To make it more convenient for debuggers to get to the value of
> inline static data members, this patch makes sure we emit definitions
> for static variables with constant initializers the same way we do
> for other static variables. This also aligns Clang closer to GCC,
> which produces CU-level definitions for inline statics and also
> emits these into `.debug_pubnames`.
>
> The implementation keeps track of newly created static data members.
> Then in `CGDebugInfo::finalize`, we emit a global `DW_TAG_variable`
> with a `DW_AT_const_value` for any of those declarations that didn't
> end up with a definition in the `DeclCache`.
>
> The newly emitted `DW_TAG_variable` will look as follows:
> ```
> 0x0000007b: DW_TAG_structure_type
> DW_AT_calling_convention (DW_CC_pass_by_value)
> DW_AT_name ("Foo")
> ...
>
> 0x0000008d: DW_TAG_member
> DW_AT_name ("i")
> DW_AT_type (0x00000062 "const int")
> DW_AT_external (true)
> DW_AT_declaration (true)
> DW_AT_const_value (4)
>
> Newly added
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
>
> 0x0000009a: DW_TAG_variable
> DW_AT_specification (0x0000008d "i")
> DW_AT_const_value (4)
> DW_AT_linkage_name ("_ZN2t2IiE1iIfEE")
> ```
>
> This patch also drops the `DW_AT_const_value` off of the declaration
> since we now always have it on the definition. This ensures that the
> `DWARFParallelLinker` can type-merge class with static members where
> we couldn't attach the constant on the declaration in some CUs.
This reverts commit 7c3707aea8.
This reverts commit cab0a19467.
This reverts commit 317481b3c8.
This reverts commit 15fc809404.
This reverts commit 470de2bbec.
https://github.com/llvm/llvm-project/pull/70639 proposes moving the
`DW_AT_const_value` on inline static members from the declaration DIE to
the definition DIE. This patch makes sure the LLDB's expression
evaluator can continue to support static initialisers even if the
declaration doesn't have a `DW_AT_const_value` anymore.
Previously the expression evaluator would find the constant for a
VarDecl from its declaration `DW_TAG_member` DIE. In cases where the
initialiser was specified out-of-class, LLDB could find it during symbol
resolution.
However, neither of those will work for constants, since we don't have a
constant attribute on the declaration anymore and we don't have
constants in the symbol table.
**Testing**
* If https://github.com/llvm/llvm-project/pull/70639 were to land
without this patch then most of the `TestConstStaticIntegralMember.py`
would start failing
This reverts commit ef3febadf6.
This caused an LLDB test failure on Linux for `lang/cpp/symbols/TestSymbols.test_dwo`:
```
make: Leaving directory '/home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/lang/cpp/symbols/TestSymbols.test_dwo'
runCmd: expression -- D::i
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. HandleCommand(command = "expression -- D::i")
1. <user expression 0>:1:4: current parser token 'i'
2. <lldb wrapper prefix>:44:1: parsing function body '$__lldb_expr'
3. <lldb wrapper prefix>:44:1: in compound statement ('{}')
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 _lldb.cpython-39-x86_64-linux-gnu.so 0x00007fbcfcb08b87
1 _lldb.cpython-39-x86_64-linux-gnu.so 0x00007fbcfcb067ae
2 _lldb.cpython-39-x86_64-linux-gnu.so 0x00007fbcfcb0923f
3 libpthread.so.0 0x00007fbd07ab7140
```
And a failure in `TestCallStdStringFunction.py` on Linux aarch64:
```
--
Exit Code: -11
Command Output (stdout):
--
lldb version 18.0.0git (https://github.com/llvm/llvm-project.git revision ef3febadf6)
clang revision ef3febadf6
llvm revision ef3febadf6
--
Command Output (stderr):
--
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. HandleCommand(command = "expression str")
1. <lldb wrapper prefix>:45:34: current parser token ';'
2. <lldb wrapper prefix>:44:1: parsing function body '$__lldb_expr'
3. <lldb wrapper prefix>:44:1: in compound statement ('{}')
#0 0x0000ffffb72a149c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lib/python3.8/site-packages/lldb/_[lldb.cpython-38-aarch64-linux-gnu.so](http://lldb.cpython-38-aarch64-linux-gnu.so/)+0x58c749c)
#1 0x0000ffffb729f458 llvm::sys::RunSignalHandlers() (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lib/python3.8/site-packages/lldb/_[lldb.cpython-38-aarch64-linux-gnu.so](http://lldb.cpython-38-aarch64-linux-gnu.so/)+0x58c5458)
#2 0x0000ffffb72a1bd0 SignalHandler(int) (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lib/python3.8/site-packages/lldb/_[lldb.cpython-38-aarch64-linux-gnu.so](http://lldb.cpython-38-aarch64-linux-gnu.so/)+0x58c7bd0)
#3 0x0000ffffbdd9e7dc (linux-vdso.so.1+0x7dc)
#4 0x0000ffffb71799d8 lldb_private::plugin::dwarf::SymbolFileDWARF::FindGlobalVariables(lldb_private::ConstString, lldb_private::CompilerDeclContext const&, unsigned int, lldb_private::VariableList&) (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lib/python3.8/site-packages/lldb/_[lldb.cpython-38-aarch64-linux-gnu.so](http://lldb.cpython-38-aarch64-linux-gnu.so/)+0x579f9d8)
#5 0x0000ffffb7197508 DWARFASTParserClang::FindConstantOnVariableDefinition(lldb_private::plugin::dwarf::DWARFDIE) (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lib/python3.8/site-packages/lldb/_[lldb.cpython-38-aarch64-linux-gnu.so](http://lldb.cpython-38-aarch64-linux-gnu.so/)+0x57bd508)
```
https://github.com/llvm/llvm-project/pull/70639 proposes moving the
`DW_AT_const_value` on inline static members from the declaration DIE to
the definition DIE. This patch makes sure the LLDB's expression
evaluator can continue to support static initialisers even if the
declaration doesn't have a `DW_AT_const_value` anymore.
Previously the expression evaluator would find the constant for a
VarDecl from its declaration `DW_TAG_member` DIE. In cases where the
initialiser was specified out-of-class, LLDB could find it during symbol
resolution.
However, neither of those will work for constants, since we don't have a
constant attribute on the declaration anymore and we don't have
constants in the symbol table.
**Testing**
* If https://github.com/llvm/llvm-project/pull/70639 were to land
without this patch then most of the `TestConstStaticIntegralMember.py`
would start failing
During the recent refactoring (b120fe8d32) this enum was moved out of `RecordDecl`. During post-commit review it was found out that its association with `RecordDecl` should be expressed in the name.
This effectively moves a few functions from protected to public. In any
case, for the sake of having a cleaner SymbolFileDWARF API, it's better
if it's not a friend of a one of its consumers, DWARFASTParserClang.
Another effect of this change is that I can use SymbolFileDWARF for the
out-of-tree mojo dwarf parser, which relies on pretty much the same
functions that DWARFASTParserClang needs from SymbolFileDWARF.
As a followup of https://github.com/llvm/llvm-project/pull/67851, I'm
defining a new namespace `lldb_plugin::dwarf` for the classes in this
Plugins/SymbolFile/DWARF folder. This change is very NFC and helped me
with exporting the necessary symbols for my out-of-tree language plugin.
The only class that I didn't change is ClangDWARFASTParser, because that
shouldn't be in the same namespace as the generic language-agnostic
dwarf parser.
It would be a good idea if other plugins follow the same namespace
scheme.
**Background**
Prior to DWARFv4, there was no clear normative text on how to handle
static data members. Non-normative text suggested that compilers should
use `DW_AT_external` to mark static data members of structrues/unions.
Clang does this consistently. However, GCC doesn't, e.g., when the
structure/union is in an anonymous namespace (which is C++ standard
conformant). Additionally, GCC never emits `DW_AT_data_member_location`s
for union members (regardless of storage linkage and storage duration).
Since DWARFv5 (issue 161118.1), static data members get emitted as
`DW_TAG_variable`.
LLDB used to differentiate between static and non-static members by
checking the `DW_AT_external` flag and the absence of
`DW_AT_data_member_location`. With
[D18008](https://reviews.llvm.org/D18008) LLDB started to pretend that
union members always have a `0` `DW_AT_data_member_location` by default
(because GCC never emits these locations).
In [D124409](https://reviews.llvm.org/D124409) LLDB stopped checking the
`DW_AT_external` flag to account for the case where GCC doesn't emit the
flag for types in anonymous namespaces; instead we only check for
presence of `DW_AT_data_member_location`s.
The combination of these changes then meant that LLDB would never
correctly detect that a union has static data members.
**Solution**
Instead of unconditionally initializing the `member_byte_offset` to `0`
specifically for union members, this patch proposes to check for both
the absence of `DW_AT_data_member_location` and `DW_AT_declaration`,
which consistently gets emitted for static data members on GCC and
Clang.
We initialize the `member_byte_offset` to `0` anyway if we determine it
wasn't a static. So removing the special case for unions makes this code
simpler to reason about.
Long-term, we should just use DWARFv5's new representation for static
data members.
Fixes#68135
Currently this non-trivial calculation is repeated multiple times,
making it hard to reason about when the
`byte_offset`/`member_byte_offset` is being set or not.
This patch simply moves all those instances of the same calculation into
a helper function.
We return an optional to remain an NFC patch. Default initializing the
offset would make sense but requires further analysis and can be done in
a follow-up patch.
LLDB doesn't yet have a TypeSystemRust implemented however it is used to debug Rust applications. Most of the types map well enough to Clang types and there are python formatters implemented to display those types reasonably well in a debugger.
However, Rust enums are completely ignored by LLDB as Clang never emits DW_TAG_variant_part inside DW_TAG_structure_type
This diff adds a parser for DW_TAG_variant_part (Rust-only) that creates a matching valid Clang declaration to the Rust enum. As long as there is enough information and all fields have correct offsets synthetic/summary providers can be implemented to display it correctly when debugging Rust code
Differential Revision: https://reviews.llvm.org/D149213
This replaces two radar links with improved comments explaining the
underlying issues.
- The first issue is working around a compiler bug that was fixed in
f454dfb6b5.
- The second issue is an invariant that doesn't actually hold. The
latter was marked as FIXME but there was nothing in the radar about a
possible alternative solution.
Both radars were closed.
The goal of this patch is to make it easier to reason about the state of
ObjCLanguage::MethodName. I do that in several ways:
- Instead of using the constructor directly, you go through a factory
method. It returns a std::optional<MethodName> so either you got an
ObjCLanguage::MethodName or you didn't. No more checking if it's valid
to know if you can use it or not.
- ObjCLanguage::MethodName is now immutable. You cannot change its
internals once it is created.
- ObjCLanguage::MethodName::GetFullNameWithoutCategory previously had a
parameter that let you get back an empty string if the method had no
category. Every caller of this method was enabling this behavior so I
dropped the parameter and made it the default behavior.
- No longer store all the various components of the method name as
ConstStrings. The relevant `Get` methods now return llvm::StringRefs
backed by the MethodName's internal storage. The lifetime of these
StringRefs are tied to the MethodName itself, so if you need to
persist these you need to create copies.
Differential Revision: https://reviews.llvm.org/D149914
**Summary**
When filling out the LayoutInfo for a structure with the offsets
from DWARF, LLDB fills gaps in the layout by creating unnamed
bitfields and adding them to the AST. If we don't do this correctly
and our layout has overlapping fields, we will hat an assertion
in `clang::CGRecordLowering::lower()`. Specifically, if we have
a derived class with a VTable and a bitfield immediately following
the vtable pointer, we create a layout with overlapping fields.
This is an oversight in some of the previous cleanups done around this
area.
In `D76808`, we prevented LLDB from creating unnamed bitfields if there
was a gap between the last field of a base class and the start of a bitfield
in the derived class.
In `D112697`, we started accounting for the vtable pointer. The intention
there was to make sure the offset bookkeeping accounted for the
existence of a vtable pointer (but we didn't actually want to create
any AST nodes for it). Now that `last_field_info.bit_size` was being
set even for artifical fields, the previous fix `D76808` broke
specifically for cases where the bitfield was the first member of a
derived class with a vtable (this scenario wasn't tested so we didn't
notice it). I.e., we started creating redundant unnamed bitfields for
where the vtable pointer usually sits. This confused the lowering logic
in clang.
This patch adds a condition to `ShouldCreateUnnamedBitfield` which
checks whether the first field in the derived class is a vtable ptr.
**Testing**
* Added API test case
Differential Revision: https://reviews.llvm.org/D150591
This patch adds a new private helper
`DWARFASTParserClang::ShouldCreateUnnamedBitfield` which
`ParseSingleMember` whether we should fill the current gap
in a structure layout with unnamed bitfields.
Extracting this logic will allow us to add additional
conditions in upcoming patches without jeoperdizing readability
of `ParseSingleMember`.
We also store some of the boolean conditions in local variables
to make the intent more obvious.
Differential Revision: https://reviews.llvm.org/D150590
The purpose of this method is to get the list of attributes of a
DebugInfoEntry. Prior to this change we were passing in a mutable
reference to a DWARFAttributes object and having the method fill it in
for us while returning the size of the filled out list. But
instead of doing that, we can just return a `DWARFAttributes` object
ourselves since every caller creates a new list before calling
GetAttributes.
Differential Revision: https://reviews.llvm.org/D150402
Similar to dw_form_t, dw_attr_t is typedef'd to be a uint16_t. LLVM
defines their type `llvm::dwarf::Attribute` as an enum backed by a
uint16_t. Switching to the LLVM type buys us type checking and the
requirement of explicit casts.
Differential Revision: https://reviews.llvm.org/D150299
We have a handful of places in LLDB where we try to outsmart the logic
in Mangled to determine whether a string is mangled or not. There's at
least one place (*) where we are getting this wrong and causes a subtle
bug. The `cstring_is_mangled` is cheap enough that we should always rely
on it to determine whether a string is mangled or not.
(*) `ObjectFileMachO` assumes that a symbol that starts with a double
underscore (such as `__pthread_kill`) is mangled. That's mostly
harmless, until you use `function.name-without-args` in the frame
format. The formatter calls `Symbol::GetNameNoArguments()` which is a
wrapper around `Mangled::GetName(ePreferDemangledWithoutArguments)`. The
latter will first try using the appropriate language plugin to get the
demangled name without arguments, and if that fails, falls back to
returning the demangled name. Because we forced Mangled to treat the
symbol as a mangled name (even though it's not) there's no demangled
name. The result is that frames don't show any symbol at all.
Differential revision: https://reviews.llvm.org/D148846
The function DWARFASTParserClang::ParsePointerToMemberType attempts to make
two pointers and then immediately tries to dereference them, without
verifying that the pointesr were successfully created. Sometimes the pointer
creation fails, and the dereference then causes a segfault. This add a check
that the pointers are non-null before attempting to dereference them.
In an upcoming patch, D142556, Clang is proposed to be changed to emit
line locations that are inlined at line 0. This clashed with the behavior of
GetDIENamesAndRanges() which used 0 as a default value to determine if
file, line or column numbers had been set. Users of that function then
checked for any non-0 values when setting up the call site:
if (call_file != 0 || call_line != 0 || call_column != 0)
[...]
which did not work with the Clang change since all three values then
could be 0.
This changes the function to use std::optional to catch non-set values
instead.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D142552
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
Note that those functions on the left hand side are soft-deprecated in
favor of those on the right hand side:
getMinSignedBits -> getSignificantBits
getNullValue -> getZero
isNullValue -> isZero
isOneValue -> isOne
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Depends on D139955
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
This came out of from https://discourse.llvm.org/t/dwarf-dwp-4gb-limit/63902
With big binaries we can have .dwp files where .debug_info.dwo section can grow
beyond 4GB. We would like to support this in LLVM and in LLDB.
The plan is to enable manual parsing of cu/tu index in DWARF library
(https://reviews.llvm.org/D137882), and then
switch internal index data structure to 64 bit.
For the second part is to enable 64bit offset support in LLDB with
this patch.
Depends on D139955
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D138618
This reverts commit 19128792e2.
As pointed out in https://reviews.llvm.org/D143652 this implementation
doesn't quite work for subobject constructors/destructors because DWARF
can map multiple definitions of a ctor/dtor to the same specification DIE.
With the current implementation we would pick the first definition we
find and use that linkage name which means we can sometimes pick the
wrong dtor/ctor and fail to execute a valid expression.
Differential Revision: https://reviews.llvm.org/D143652
This relands a patch previously reverted
in `181d6e24ca3c09bfd6ec7c3b20affde3e5ea9b40`.
This wasn't quite working on Linux because we
weren't populating the manual DWARF index with
`DW_TAG_imported_declaration`. The relanded patch
does this.
**Summary**
This patch makes the expression evaluator understand
namespace aliases.
This will become important once `std::ranges` become
more widespread since `std::views` is defined as:
```
namespace std {
namespace ranges::views {}
namespace views = ranges::views;
}
```
**Testing**
* Added API test
Differential Revision: https://reviews.llvm.org/D143398
This relands the commit previously reverted in
`d2cc2c5610ffa78736aa99512bc85a85417efb0a` due to failures on Linux
when debugging split-debug-info enabled executables.
The problem was we called `SymbolFileDWARF::FindFunctions` directly
instead of `Module::FindFunctions` which resulted in a nullptr
dereference because the backing `SymbolFileDWARFDwo` didn't have
an index attached to it. The relanded version calls `Module::FindFunctions`
instead.
Differential Revision: https://reviews.llvm.org/D143652
**Summary**
This patch addresses the case where we have a `DW_AT_external`
subprogram for a constructor (and/or destructor) that doesn't carry
a `DW_AT_linkage_name` attribute. The corresponding DIE(s) that
represent the definition will have a linkage name, but if the name
contains constructs that LLDBs fallback mechanism for guessing mangled
names to resolve external symbols doesn't support (e.g., abi-tags)
then we end up failing to resolve the function call.
We address this by trying to find the linkage name before we create
the constructor/destructor decl, which will get attached using
an `AsmLabelAttr` to make symbol resolution easier.
**Testing**
* Added API test
Differential Revision: https://reviews.llvm.org/D143652
**Summary**
This patch makes the expression evaluator understand
namespace aliases.
This will become important once `std::ranges` become
more widespread since `std::views` is defined as:
```
namespace std {
namespace ranges::views {}
namespace views = ranges::views;
}
```
**Testing**
* Added API test
Differential Revision: https://reviews.llvm.org/D143398