Skip to content

[LLDB] static const fields of type unsigned char cannot be inspected #119101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Walnut356 opened this issue Dec 8, 2024 · 4 comments
Open

[LLDB] static const fields of type unsigned char cannot be inspected #119101

Walnut356 opened this issue Dec 8, 2024 · 4 comments
Labels

Comments

@Walnut356
Copy link

The sample code is roughly the debuginfo layout of Rust enums, written in C++ and compiled via cl.exe. Worth pointing out that Rust uses TypeSystemClangCommon at the moment. For the enum type and non-uchar integer types, SBTypeStaticField::GetConstantValue() returns the static field's initializer value. For unsigned char it always returns an invalid SBValue

version: 19.1.1

main.cpp:

#include <stdio.h>

union enum2 {
    enum VariantNames { First, Second };
    struct Variant0 {
        struct First {
            int a;
        } value;
        const static VariantNames NAME = enum2::VariantNames::First;
        const static unsigned char DISCR_EXACT = 1; // <-- relevant value
    } variant0;

    unsigned long tag;
};

int main()
{
    enum2 val = enum2{};
    printf("Hello World!");
}

Output:

(lldb) script lldb.frame.FindVariable("val").GetType()
union enum2 {
    struct Variant0 {
        struct First {
            int a;
        };
        static const enum2::VariantNames NAME = 0;
        static const unsigned char DISCR_EXACT;
    ...
}

Output if DISCR_EXACT is changed to unsigned long long:

(lldb) script lldb.frame.FindVariable("val").GetType()
union enum2 {
    struct Variant0 {
        struct First {
            int a;
        };
        static const enum2::VariantNames NAME = 0;
        static const unsigned long long DISCR_EXACT = 1ULL;
    ...
}
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 2024

@llvm/issue-subscribers-lldb

Author: Walnut (Walnut356)

The sample code is roughly the debuginfo layout of Rust enums, written in C++ and compiled via `cl.exe`. Worth pointing out that Rust uses `TypeSystemClangCommon` at the moment. For the enum type and non-uchar integer types, `SBTypeStaticField::GetConstantValue()` returns the static field's initializer value. For unsigned char it always returns an invalid `SBValue`

version: 19.1.1

main.cpp:

#include &lt;stdio.h&gt;

union enum2 {
    enum VariantNames { First, Second };
    struct Variant0 {
        struct First {
            int a;
        } value;
        const static VariantNames NAME = enum2::VariantNames::First;
        const static unsigned char DISCR_EXACT = 1; // &lt;-- relevant value
    } variant0;

    unsigned long tag;
};

int main()
{
    enum2 val = enum2{};
    printf("Hello World!");
}

Output:

(lldb) script lldb.frame.FindVariable("val").GetType()
union enum2 {
    struct Variant0 {
        struct First {
            int a;
        };
        static const enum2::VariantNames NAME = 0;
        static const unsigned char DISCR_EXACT;
    ...
}

Output if DISCR_EXACT is changed to unsigned long long:

(lldb) script lldb.frame.FindVariable("val").GetType()
union enum2 {
    struct Variant0 {
        struct First {
            int a;
        };
        static const enum2::VariantNames NAME = 0;
        static const unsigned long long DISCR_EXACT = 1ULL;
    ...
}

@jimingham
Copy link
Collaborator

It isn't entirely correct to say that these values can't be viewed. Debugging your example:

(lldb) expr enum2::Variant0::DISCR_EXACT
(const unsigned char) $0 = '\x01'
(lldb) expr enum2::Variant0::NAME
(const enum2::VariantNames) $1 = First

Seeing a static variable in a struct's value by inspecting its type is a bit of a roundabout way of getting the value, though that should also work.

It's also a bit worrisome that target var can't find them:

(lldb) target var enum2::Variant0::DISCR_EXACT
error: can't find global variable 'enum2::Variant0::DISCR_EXACT'

If expr can find the symbol, target var should also be able to find it.

@Michael137
Copy link
Member

Michael137 commented Dec 12, 2024

Hmmm are you generating DWARF or PDB? Your example (using GetType) works just fine for me on macOS (using DWARF)

@Walnut356
Copy link
Author

Hmmm are you generating DWARF or PDB? Your example (using GetType) works just fine for me on macOS (using DWARF)

Whoops sorry, this is for PDB

Seeing a static variable in a struct's value by inspecting its type is a bit of a roundabout way of getting the value, though that should also work.

This is almost exclusively used for the debugger visualizer script's SyntheticProviders, so it's convenient to grab it from the type since we already have it.

Funnily enough, I testing out the commands on my end and I get the exact opposite issue. expr doesn't work, but target var does. Worth noting it was compiled via Visual Studio 2022 with the default Debug configuration

(lldb) expr enum2::Variant0::DISCR_EXACT
error: Couldn't look up symbols:Unknown>...
  enum2::Variant0::DISCR_EXACT
Hint: The expression tried to call a function that is not present in the target, perhaps because it was optimized out by the compiler.
(lldb) target var enum2::Variant0::DISCR_EXACT
(const unsigned char) enum2::Variant0::DISCR_EXACT = '\x01'

I also tried using the expr command on a rust binary and it unfortunately errors out for unrelated reasons:

enum definition:

pub enum Container {
    First(u32),
    Second{val: u64, val2: i8},
    Third,
}

output (via codelldb):

/py lldb.frame.FindVariable("sum_val").GetChildMemberWithName("variant0").GetType()
"struct Variant0 {
    enum2$<sample::Container>::First value;
    static const enum2$<sample::Container>::VariantNames NAME = 0;
    static const unsigned long long DISCR_EXACT = 0ULL;
}"
/cmd expr enum2$<sample::Container::Variant0::DISCR_EXACT
error: <user expression 56>:1:16: no member named 'Container' in namespace 'sample'
    1 | enum2$<sample::Container>::Variant0::DISCR_EXACT
      |        ~~~~~~~~^

I am using this patch of the rust compiler. LLDB was unable to inspect non-const static fields at all, so the patch adds the const tag and forces the generated DISCR_EXACT type to u64

Rust has this explanation of the debuginfo generation, and the code that builds the associated consts is a bit further down

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants