This is an archive of the discontinued LLVM Phabricator instance.

[lldb] [Platform] Support synthesizing siginfo_t
ClosedPublic

Authored by mgorny on Jan 19 2022, 11:17 AM.

Details

Summary

Support synthesizing the siginfo_t type from the Platform plugin.
This type is going to be used by LLDB client to process the raw siginfo
data received from lldb-server without the necessity of relying
on target's debug info being present.

Diff Detail

Event Timeline

mgorny requested review of this revision.Jan 19 2022, 11:17 AM
mgorny created this revision.

My current test program is:

#!/usr/bin/env python

import lldb

raw_data = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00up\n\x00\xe8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

lldb.SBDebugger.Initialize()
try:
    dbg = lldb.SBDebugger.Create()
    try:
        t = dbg.CreateTarget("/home/mgorny/git/llvm-project/build/a.out")
        assert t
        typ = list(t.FindTypes("siginfo_t"))[0]
        assert typ
        typ2 = t.GetPlatform().GetSiginfoType(t)
        assert typ2
        data = lldb.SBData()
        data2 = lldb.SBData()
        error = lldb.SBError()
        data.SetData(error, raw_data, lldb.eByteOrderLittle, 8)
        print(t.CreateValueFromData("siginfo", data, typ))
        print(t.CreateValueFromData("siginfo2", data, typ2))
    finally:
        lldb.SBDebugger.Destroy(dbg)
finally:
    lldb.SBDebugger.Terminate()
mgorny updated this revision to Diff 401364.Jan 19 2022, 12:11 PM

Cover more union members.

Hmm, maybe for the sub-structs, it'd be better to use TypeSystemClang::CreateStructForIdentifier().

mgorny updated this revision to Diff 401378.Jan 19 2022, 1:08 PM

Use CreateStructForIdentifier() whenever possible. Describe the remaining union members.

Open question: do we care for 100% correct SPARC support? Given that it has different _sigfault layout, it adds some complexity while LLDB doesn't seem to support SPARC at all.

mgorny updated this revision to Diff 401421.Jan 19 2022, 3:25 PM

Initial PoC unit test — the idea is to verify field offsets and sizes against known values taken from real siginfo_t.

mgorny updated this revision to Diff 401582.Jan 20 2022, 3:34 AM

Cover all fields with tests and add a test input generator.

mgorny updated this revision to Diff 401585.Jan 20 2022, 3:56 AM

Put the common test code into a common init function, add tests for armv7, arm64, i386, ppc64le.

mgorny updated this revision to Diff 402043.Jan 21 2022, 10:55 AM
mgorny retitled this revision from siginfo_t synthesis WIP to [lldb] [Platform] Support synthesizing siginfo_t.
mgorny edited the summary of this revision. (Show Details)

Simplify the tests to use dotted member notation for field lookup. Make the test utility generate exact test code.

mgorny updated this revision to Diff 402055.Jan 21 2022, 11:30 AM

Update following instrumentation changes.

mgorny updated this revision to Diff 402110.Jan 21 2022, 2:21 PM

Turn PlatformLinuxTest into a more generic PlatformSiginfoTest, to improve code reuse between platforms. Start preparing for testing FreeBSD.

mgorny updated this revision to Diff 402113.Jan 21 2022, 2:51 PM

Add tests for FreeBSD (no implementation yet).

mgorny updated this revision to Diff 402116.Jan 21 2022, 3:10 PM

Implemented FreeBSD.

mgorny updated this revision to Diff 402193.Jan 22 2022, 1:05 AM

Combine the tests for various 32-bit and 64-bit arches, as they have the same offset-size pairs. Instead of repeating them, just iterate over the list of arches.

mgorny updated this revision to Diff 402208.Jan 22 2022, 5:49 AM

Add NetBSD.

Adding Alex for the plugin dependency aspect. I don't think this dep is wrong (it's pretty hard to pretend we don't at least have a C language), but he may want to say something about this.

The patch itself is somewhat repetitive, but otherwise seems ok.

I am a bit curious about the __lldb prefix. I'm wondering if there's a way to avoid having it, while still maintaining isolation from any type with the same name coming from the debug info. I'm thinking about putting it in some kind of an anonymous namespace or something... Does anyone know if that works?

lldb/source/API/SBPlatform.cpp
672 ↗(On Diff #402208)

??

lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
323

we don't

lldb/unittests/Platform/PlatformSiginfoTest.cpp
84

drop c_str()

110

Other platform APIs seem to take an ArchSpec or even a Triple, so doing that would be more consistent *and* make your job here easier.

The GetSiginfoType API seems awkward to me. It requires I get the data itself from some other source and then cast it to this type myself. I'm assuming in the fullness of time, there will be a GetSiginfoData call, and then I have to put the two together? The only reason I can see to have separate "GetType" and "GetData" calls is if there's some useful way to get the data blob that doesn't go through lldb.

After all, if we had:

SBValue SBThread::GetSiginfoValue();

API you can still get the type and data back out of the SBValue if you needed them. But I am pretty sure most uses will be to query the values of its child members, which makes the value returning API more convenient.

At the lldb_private layer, it's fine to separate the two, but when you go to present this to the outside world through commands or API's we try to keep the API set more compact.

jingham added a comment.EditedJan 25 2022, 10:38 AM

Adding Alex for the plugin dependency aspect. I don't think this dep is wrong (it's pretty hard to pretend we don't at least have a C language), but he may want to say something about this.

I think we need to have a way to express types that the base platform has so we can present them in a structured way to users. Formally, you could express this by saying that we need a "platform language" reflecting how that platform vends it's API's at the lowest level. This would have been Pascal for classic MacOS way back in the day, and maybe Lisp for Lisp machines. But IRL all the platforms we are likely to deal with express their lowest level system API's in C, so it seems okay to have that be an implicit assumption till we come across a system that we want to support and for which C isn't one of the low level system languages.

The patch itself is somewhat repetitive, but otherwise seems ok.

I am a bit curious about the __lldb prefix. I'm wondering if there's a way to avoid having it, while still maintaining isolation from any type with the same name coming from the debug info. I'm thinking about putting it in some kind of an anonymous namespace or something... Does anyone know if that works?

This will be the actual type of an SBValue, as is the case in other instances where we've made up types, so users will see this type if they look closely. So it should be clear from the name that this is just an artificial type lldb made up. __lldb_whatever expresses that pretty clearly, but I'm worried some reasonable looking name in an anonymous namespace would send users off on a wild goose chase.

mgorny marked 4 inline comments as done.Jan 25 2022, 11:18 AM
mgorny added inline comments.
lldb/source/API/SBPlatform.cpp
672 ↗(On Diff #402208)

Sorry, debug leftover ;-).

mgorny updated this revision to Diff 402979.Jan 25 2022, 11:18 AM
mgorny marked an inline comment as done.

Implemented the requested changes.

Hmm, I think I've exposed it via SBPlatform because originally I planned on writing the tests in Python. However, it ended up being tested through unittests after all, so I think I can remove that part. Lemme try.

mgorny updated this revision to Diff 402991.Jan 25 2022, 12:04 PM

Remove the unnecessary API part.

jingham added a comment.EditedJan 25 2022, 12:44 PM

Remove the unnecessary API part.

In the end, you will want some SB API exposing this information so users can do something with it. I think returning the SBValue for the Thread is the right way to go. I see you're doing that in https://reviews.llvm.org/D118055.

jingham accepted this revision.Jan 25 2022, 12:47 PM

This looks fine to me.

This revision is now accepted and ready to land.Jan 25 2022, 12:47 PM
labath accepted this revision.Jan 26 2022, 4:13 AM

I am a bit curious about the __lldb prefix. I'm wondering if there's a way to avoid having it, while still maintaining isolation from any type with the same name coming from the debug info. I'm thinking about putting it in some kind of an anonymous namespace or something... Does anyone know if that works?

This will be the actual type of an SBValue, as is the case in other instances where we've made up types, so users will see this type if they look closely. So it should be clear from the name that this is just an artificial type lldb made up. __lldb_whatever expresses that pretty clearly, but I'm worried some reasonable looking name in an anonymous namespace would send users off on a wild goose chase.

Yeah, that makes sense.

Thanks for the review. I'm going to wait with the merging until the other patch is reviewed, in case there are any API changes required here.

This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptJan 27 2022, 4:34 AM