This is an archive of the discontinued LLVM Phabricator instance.

[BPF][DebugInfo] Use .BPF.ext for line info when DWARF is not available
ClosedPublic

Authored by eddyz87 on Apr 24 2023, 5:49 AM.

Details

Summary

"BTF" is a debug information format used by LLVM's BPF backend.
The format is much smaller in scope than DWARF, the following info is
available:

  • full set of C types used in the binary file;
  • types for global values;
  • line number / line source code information .

BTF information is embedded in ELF as .BTF and .BTF.ext sections.
Detailed format description could be found as a part of Linux Source
tree, e.g. here: [1].

This commit modifies llvm-objdump utility to use line number
information provided by BTF if DWARF information is not available.
E.g., the goal is to make the following to print source code lines,
interleaved with disassembly:

$ clang --target=bpf -g test.c -o test.o
$ llvm-strip --strip-debug test.o
$ llvm-objdump -Sd test.o

test.o:	file format elf64-bpf

Disassembly of section .text:

<foo>:
; void foo(void) {
	r1 = 0x1
;   consume(1);
	call -0x1
	r1 = 0x2
;   consume(2);
	call -0x1
; }
	exit

A common production use case for BPF programs is to:

  • compile separate object files using clang with -g -c flags;
  • link these files as a final "static" binary using bpftool linker ([2]).

The bpftool linker discards most of the DWARF sections
(line information sections as well) but merges .BTF and .BTF.ext sections.
Hence, having llvm-objdump capable to print source code using .BTF.ext
is valuable.

The commit consists of the following modifications:

  • llvm/lib/DebugInfo/BTF aka DebugInfoBTF component is added to host the code needed to process BTF (with assumption that BTF support would be added to some other tools as well, e.g. llvm-readelf):
    • DebugInfoBTF provides llvm::BTFParser class, that loads information from .BTF and .BTF.ext sections of a given object::ObjectFile instance and allows to query this information. Currently only line number information is loaded.
    • DebugInfoBTF also provides llvm::BTFContext class, which is an implementation of DIContext interface, used by llvm-objdump to query information about line numbers corresponding to specific instructions.
  • Structure DILineInfo is modified with field LineSource.

    DIContext interface uses DILineInfo structure to communicate line number and source code information. Specifically, DILineInfo::Source field encodes full file source code, if available. BTF only stores source code for selected lines of the file, not a complete source file. Moreover, stored lines are not guaranteed to be sorted in a specific order.

    To avoid reconstruction of a file source code from a set of available lines, this commit adds LineSource field instead.
  • Symbolize class is modified to use BTFContext instead of DWARFContext when DWARF sections are not available but BTF sections are present in the object file. (Symbolize is instantiated by llvm-objdump).
  • Integration and unit tests.

Note, that DWARF has a notion of "instruction sequence".
DWARF implementation of DIContext::getLineInfoForAddress() provides
inexact responses if exact address information is not available but
address falls within "instruction sequence" with some known line
information (see DWARFDebugLine::LineTable::findRowInSeq()).

BTF does not provide instruction sequence groupings, thus
getLineInfoForAddress() queries only return exact matches.
This does not seem to be a big issue in practice, but output
of the llvm-objdump -Sd might differ slightly when BTF
is used instead of DWARF.

[1] https://www.kernel.org/doc/html/latest/bpf/btf.html
[2] https://github.com/libbpf/bpftool

Depends on https://reviews.llvm.org/D149501

Diff Detail

Event Timeline

eddyz87 created this revision.Apr 24 2023, 5:49 AM
Herald added a reviewer: MaskRay. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
eddyz87 updated this revision to Diff 517440.Apr 26 2023, 8:27 PM

Reorganized to report errors, added objdump test-case.

eddyz87 updated this revision to Diff 518092.Apr 28 2023, 4:45 PM

Reorganized to provide BTFParser class, added unit tests.

eddyz87 edited the summary of this revision. (Show Details)Apr 28 2023, 4:49 PM
yonghong-song added a subscriber: yonghong-song.EditedMay 1 2023, 11:29 AM

The following is the immediate use case why this patch will help BPF community.
Currently bpftool implements static linking as lld does not support it. The static linking looks like below:

    1. Let us say we have three files t1.c, t2.c, t3.c, they call compiled with '-target bpf -O2 -mcpu=v3 -g -c' and generates t1.o, t2.0, t3.o
    2. To minimize runtime overhead, we would like to produce just one binary say t_final.o which contains a single BTF section and a single BTF.ext section, and this is bpf linking step implemented in bpftool.
  1. The t_final.o is used by applicaiton (libbpf library) to extract necessary insn/relocation/btf etc. and process them and load them into the kernel.

The step 3 may be repeated many times (application restart, etc., repeated run e.g., for tracing app, etc.) so it is critical that bpf linking (bpftool) can generate a .o file which can be processed and loaded into kernel as faster as possible.

So the step 2 does the following with bpftool:

  • merging all code sections with all .o files and do necessary relocation
  • merging all .BTF/.BTF.ext sections into a single one, not that to save space, deduplication is done to minimize BTF size.
  • remove dwarf sections as they are not cirtical to BPF program execution. Also, with bpf skeleton, t_final.o is presented as a blob of data and embedded as a special string constant and taking up application memory space. So removing dwarf data can save application memory usage as well.

The end result is that t_final.o does not have dwarf sections and only have .BTF/.BTF.ext sections. The BTF sections contains line number info and verifier uses such information to deplay verifier logs annotated with source code.
But llvm-objdump -S won't work any more. We would like it works with BTF to show source annotated asm code if dwarf is not available.

eddyz87 updated this revision to Diff 518565.May 1 2023, 2:21 PM
eddyz87 edited the summary of this revision. (Show Details)

Unit test changed to use #pragma pack instead of attribute((packed)) to satisfy MSVC unit tests build.

eddyz87 updated this revision to Diff 518581.May 1 2023, 3:24 PM

Fix incorrect path substitution for interleaved-source-test.ll on windows.

eddyz87 published this revision for review.May 1 2023, 4:32 PM
eddyz87 added a reviewer: yonghong-song.

Hi James, Fangrui,

Could you please take a look at this modification for llvm-objdump?
This change would be quite helpful for people developing BPF programs using CLANG.

Herald added a project: Restricted Project. · View Herald TranscriptMay 1 2023, 4:32 PM

Hi @jhenderson, @MaskRay,

Sorry to bother you, but could you please take a look at this revision?
I have other BPF related changes that depend on it...

yonghong-song accepted this revision.May 7 2023, 10:27 PM

From BPF perspective, it looks good to me. The only thing I am not sure is in struct DILineInfo, std::optional<StringRef> LineSource; is added which sounds a little bit weird since 'Source' is there. But the 'LineSource' is used to differentiate from dwarf 'Source'. If this is not preferred, we could remove it and hide the LineSource info in BTFContext instead.

@MaskRay @jhenderson I really appreciate your opinions on this BTF addition to llvm-objdump. Thanks!

This revision is now accepted and ready to land.May 7 2023, 10:27 PM

From BPF perspective, it looks good to me. The only thing I am not sure is in struct DILineInfo, std::optional<StringRef> LineSource; is added which sounds a little bit weird since 'Source' is there. But the 'LineSource' is used to differentiate from dwarf 'Source'. If this is not preferred, we could remove it and hide the LineSource info in BTFContext instead.

Sorry, not sure I understand. The only way to preserve old interface for DILineInfo that I see is to collect all lines stored in .BTF.ext, sort those lines by file name, line number and create std::string instances with "fake" source code for each file (which is a bit wasteful from cpu/memory pov). Is that what you mean or am I missing something?

Sorry, not sure I understand. The only way to preserve old interface for DILineInfo that I see is to collect all lines stored in .BTF.ext, sort those lines by file name, line number and create std::string instances with "fake" source code for each file (which is a bit wasteful from cpu/memory pov). Is that what you mean or am I missing something?

Okay, I see. I thought we could add 'LineSource' to BTFContext, but that will need to change the generic llvm-objdump interface (casting to BTFContext). Or we could reuse 'Source' by *constructing* similar-to-dwarf source from BTF as you mentioned above, but it is somehow a waste based on you explanation in the above.

There are different ways to solve this. I would like to hear @MaskRay and @jhenderson 's opinion.

jhenderson added a subscriber: dblaikie.

Sorry for not getting back to you: I'm in the midst of some fairly major work that means I only have minimal time for reviewing. I'll try to get back to you in the next week or two, if nobody else does. I've added @dblaikie, who has looked at symbolizer stuff and knows a lot about DWARF and the debug library interface.

Sorry for not getting back to you: I'm in the midst of some fairly major work that means I only have minimal time for reviewing. I'll try to get back to you in the next week or two, if nobody else does. I've added @dblaikie, who has looked at symbolizer stuff and knows a lot about DWARF and the debug library interface.

No problem, thank you for letting me know.
No rush from my side, just would be great to have this feature by LLVM 17 release.

Hi @jhenderson, @dblaikie,

Could you please take a look at this revision?

jhenderson resigned from this revision.Jun 15 2023, 3:44 AM

Sorry, having skimmed this again, I realistically don't think I'll ever get around to looking at this patch properly, as it's too complex for me to be able to understand in the small amounts of time I have available to review.

Add @nickdesaulniers as the reviewer as well. @nickdesaulniers could you help take a look at the patch as well?

yes; I'm traveling but will take a look later this week.

Initial code review pass

llvm/include/llvm/DebugInfo/BTF/BTFParser.h
34

IIRC, I think you can move this using statement into the class definition to scope its use within the class? Otherwise using in headers makes me nervous.

45

why std::map over something like llvm::DenseMap?
https://llvm.org/docs/ProgrammersManual.html#llvm-adt-densemap-h

llvm/lib/DebugInfo/BTF/BTFContext.cpp
31–34

dump is super common for most classes in LLVM when debugging. If you're not going to provide a meaningful definition, I think you can do so in the header file. Same for the constructor above.

38

plz no auto

40–42

pretty sure this will prevent NVRO. Just declare Result first, then always return it.

52

here you can return {};

60

here you can return {};

67–69

here you can return {};

72

probably here you can return {};

79

plz no auto here

llvm/lib/DebugInfo/BTF/BTFParser.cpp
105

plz no auto here

plz review https://llvm.org/docs/CodingStandards.html#use-auto-type-deduction-to-make-code-more-readable and update the remainder of this patch where appropriate.

llvm/tools/llvm-objdump/SourcePrinter.h
154–155

How about returning just a StringRef; in the case of failure, return a StringRef that is empty, such as a default constructed StringRef.

llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
24

unused?

26

unused?

llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
91

size_t

Apologies for my slow response. Reading...

llvm/include/llvm/DebugInfo/BTF/BTF.h
248

ditto below

MaskRay requested changes to this revision.Jun 22 2023, 7:52 PM
MaskRay added inline comments.
llvm/lib/DebugInfo/BTF/BTFParser.cpp
30

const char BTF_SECTION_NAME[] = ".BTF"

48

See https://llvm.org/docs/CodingStandards.html#anonymous-namespaces

This dangerously leaves a globally named Err which may collide with user programs if they link in LLVM.

53

{}; => {}

56
81

The "The section name to SectionRef mapping" should be attached to Sections, not the class.

87

map is slow. Here we don't need a stable iteration order. Use DenseMap<StringRef, SectionRef>

251

Nit: delete blank line.

This is not the Linux kernel community. Generally we don't add a blank line after a variable declaration. IMHO it often unnecessarily increases the number of lines without improving readability.

You may want to fix this elsewhere in the patch.

252
257

delete blank line

259

don't capitalize

260

delete blank line

277

In LLVM_ENABLE_ABI_BREAKING_CHECKS mode, in case of an error, this Expected return value will crash.

This revision now requires changes to proceed.Jun 22 2023, 7:52 PM
MaskRay added inline comments.Jun 22 2023, 9:04 PM
llvm/lib/DebugInfo/BTF/BTFContext.cpp
78

make_unqiue

llvm/lib/DebugInfo/BTF/BTFParser.cpp
135

Check whether the version is supported and add a test

176

Check whether the version is supported and add a test

211

make_unqiue

212

delete blank line

MaskRay added inline comments.Jun 22 2023, 9:04 PM
llvm/lib/DebugInfo/BTF/BTFParser.cpp
157

substr

delete blank line

215

delete blank line

218

delete blank line

221

delete blank line

226

delete blank line

288

substr

llvm/test/tools/llvm-objdump/BPF/interleaved-source-test.ll
3

We don't generally add ^;$ lines. Having these lines actually makes { } jumping with Vim difficult...

4

Some test directories, including llvm-objdump, prefer ;; for non-RUN-non-CHECK comments. This makes comments stand out (may be highlit in some editors).

15

interleaved-source-test.ll tests a BPF program with only BTF, but there is no test testing the behavior when both DWARF and BTF are present. We probably should dump the output of the original %t and the stripped %t into two text files, and check that the two text files are identical.

17

Testing the addresses below, at least for one function, will be useful.

17

You can simplify -Sd to -S as -S implies -d

28

Use --target=bpf.

I have sent https://lore.kernel.org/bpf/20230623020908.1410959-1-maskray@google.com/T/#u to replace -target bpf with --target=bpf and hopefully influenced new BPF users to migrate away from the deprecated -target

36

This doesn't check that .debug_info is not above .BTF.

FileCheck %s --implicit-check-not=.debug_ may be useful.

eddyz87 updated this revision to Diff 535840.Jun 29 2023, 9:11 AM
eddyz87 marked 41 inline comments as done.
  • styling fixes according to reviewer's comments
  • added checks for .BTF and .BTF.ext versions

Hi @nickdesaulniers , @MaskRay ,

Thank you for taking a look at this revision.
I've added requested changes, and put inline comments for a few points I don't agree with.
Could you please take a second look?

P.S.
A silly question, who has to check the "Done" box for sub-discussions, author or reviewer?

llvm/lib/DebugInfo/BTF/BTFContext.cpp
78

I defined BTFContext constructor as private and clang disallows me to call private constructor here:

unique_ptr.h:1065:34: error: calling a private constructor of class 'llvm::BTFContext'
    { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

If you strictly disprove usage of unique_ptr() I can make the constructor public.

llvm/lib/DebugInfo/BTF/BTFParser.cpp
56

Done under assumption that you refer to the error message, removed capitalization from all error messages.

81

The purpose of the comment was to explain the purpose of this class existence.
I changed comment to focus on the class itself.

288
  • substr(size_t Start, size_t N) -> substring from [Start, Start + N)
  • slice(size_t Start, size_t End) -> substring from [Start, End)

Call to StringsTable.find(0, Offset) returns the end position for string starting at Offset. Why is substr() better in this context?

llvm/test/tools/llvm-objdump/BPF/interleaved-source-test.ll
15

I've added llvm-objdump ... %t | FileCheck %s step before DWARF information stripping, so objdump output is verified for both DWARF-BTF and BTF-only versions of the object file.

llvm/tools/llvm-objdump/SourcePrinter.h
154–155

This is probably fine and no tests fail if I do such change.
However, it implies that SourcePrinter::printSources() can never print an empty line.
The original SourcePrinter::printSources() does not have such property, idk if this is important.
I included this change but I think std::optional is better because it highlights that return value is not mandatory and makes the "absent" value indicator self-explanatory.

llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
91

This is a part of the packed structure with predefined layout, the u32 value is expected in this position.

Note: structure MockData1 is used as a blob to be parsed by BTF parser in the tests below, its layout has to match BTF binary encoding.

eddyz87 updated this revision to Diff 537549.Jul 5 2023, 5:06 PM

Fix for a memory handling issue in unit tests:
Storage parameter passed to yaml::yaml2ObjectFile() has to be alive while resulting ObjectFile is used.
This updates the mock data class to own both object file and storage buffer.

Hi @nickdesaulniers , @MaskRay ,

Could you please take a look at my replies / fixes?
It would be really great if this could be sorted out before LLVM 17 release...

nickdesaulniers accepted this revision.Jul 10 2023, 2:37 PM

Could you please take a second look?

Sorry for the delays; I've been on vacation a lot lately!

A silly question, who has to check the "Done" box for sub-discussions, author or reviewer?

Anyone can, but generally a reviewer makes a comment/request, then the author of the patch marks them done as they are addressed, which denotes that the requested points have been addressed.

llvm/lib/DebugInfo/BTF/BTFContext.cpp
78

right, std::make_unique requires the constructor to be private, unfortunately. I think the code LGTM as is.

Sorry for the slow response... Weekly ping is fine if you receive no response. I am reading through this again...

For the summary:

$ clang -target bpf -g test.c -o test.o

Switch to clang --target=bpf as -target has been deprecated since Clang 3.4.
Tip: use arc diff --head=HEAD 'HEAD^' --verbatim to update the diff as well as rewriting the summary with your local commit message.

A silly question, who has to check the "Done" box for sub-discussions, author or reviewer?

Tip. The differential author can click "Done" without clicking "Submit". When arc diff 'HEAD^' or (to update the summary) arc diff --head=HEAD 'HEAD^' --verbatim uploads a new patch, the "Done" states will be sumited.
However, if you make replies to the inline comments, you need to explicitly click "Submit".

llvm/lib/DebugInfo/BTF/BTFParser.cpp
25

const variables in namespace are automatically internal linkage. static is not needed.

103

return Sections.lookup(Name);

llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
623

Use llvm::Triple::isBPF

llvm/test/tools/llvm-objdump/BPF/interleaved-source-test.ll
41

;; Check inlined source code in disassembly:

45

We can use [[#%x,]], but the convention is probably to just use ; CHECK-NEXT: <foo>:.

Thank you for the update. The code looks good, i've only got a few nits and test suggestions.

llvm/include/llvm/DebugInfo/BTF/BTFContext.h
2

See https://llvm.org/docs/CodingStandards.html#file-headers

This needs a C++ marker. Ditto elsewhere

llvm/include/llvm/DebugInfo/BTF/BTFParser.h
45

We can remove the unique_ptr indirection: DenseMap<uint64_t, BTFLinesVector> SectionLines;

If you change BTFLinesVector to use SmallVector<xxx, 0>, it will be even smaller.

56
63
76
llvm/lib/DebugInfo/BTF/BTFContext.cpp
54
66

Make the constructor public so that make_unique can be used.

78

Make the constructor public so that make_unique can be used.

DWARFContext has a public constructor as well.

llvm/lib/DebugInfo/BTF/BTFParser.cpp
103

Sorry, lookup cannot be used. The existing code is correct.

133

Make it explicit you discard the return value.

166

Make it explicit you discard the return value.

172

Make it explicit you discard the return value.

208

If C has errored, we probably should not invoke Lines->push_back({InsnOff, FileNameOff, LineOff, LineCol});

210

llvm::stable_sort(*Lines, ...) to make the behavior deterministic no matter what std::sort implementations are unused.
See https://libcxx.llvm.org/DesignDocs/UnspecifiedBehaviorRandomization.html

226

I think init (a simple method) can be inlined into parse, then we may even avoid the two Ctx.findSection(BTF...Name); calls as we can check the section name in the section iteration loop.

In addition, the new code will be more similar to hasBTFSections

272

When lower_bound is used with a custom predicate, it's usually better to use https://en.cppreference.com/w/cpp/algorithm/partition_point instead

llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
19

We normally place using namespace immediately below #include

27

Use static instead of an anonymous namespace. See https://llvm.org/docs/CodingStandards.html#anonymous-namespaces

54

Consider starting the anonymous namespace here, including all TEST( below.

eddyz87 updated this revision to Diff 539169.Jul 11 2023, 9:48 AM
eddyz87 marked 29 inline comments as done.
eddyz87 edited the summary of this revision. (Show Details)
  • changes according to comments from @MaskRay;
  • added new error condition: non-existing section name specified in the .BTF.ext line info table;
  • unit tests: changed parseError function EXPECT_PARSE_ERROR macro to preserve line info when error is reported.

Hi @MaskRay , @nickdesaulniers,

Thanks a lot for reviewing the patch!

llvm/test/tools/llvm-objdump/BPF/interleaved-source-test.ll
45

You asked to check function address in the disassembly, so I added regex to match the address. Changed to [[#%x,]] in the new version.

MaskRay accepted this revision.Jul 11 2023, 5:21 PM

Thank!

llvm/include/llvm/DebugInfo/BTF/BTFContext.h
22
llvm/test/tools/llvm-objdump/BPF/interleaved-source-test.ll
45

Ah, sounds good. This makes it clear that there is an address.

llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
15
This revision is now accepted and ready to land.Jul 11 2023, 5:21 PM
eddyz87 updated this revision to Diff 539499.Jul 12 2023, 4:31 AM
eddyz87 marked 3 inline comments as done.

Changes requested by @MaskRay in the last review round.

This revision was landed with ongoing or failed builds.Jul 12 2023, 9:51 AM
This revision was automatically updated to reflect the committed changes.

Seems to be causing a build breakage. @eddyz87 PTAL and revert if you can't fix forward quickly.
https://lab.llvm.org/buildbot/#/builders/231/builds/13875

Seems to be causing a build breakage. @eddyz87 PTAL and revert if you can't fix forward quickly.
https://lab.llvm.org/buildbot/#/builders/231/builds/13875

Specifically, it seems that the tests fail for big endian architectures.

Seems to be causing a build breakage. @eddyz87 PTAL and revert if you can't fix forward quickly.
https://lab.llvm.org/buildbot/#/builders/231/builds/13875

Specifically, it seems that the tests fail for big endian architectures.

8130166b92d513acabec3962cd91baa54b5f095a should hopefully fix the unittest for big-endian targets.
The big-endian functionality is correct, though, just the unittest needs more care.

Hi @MaskRay,

Sorry, I was away from the PC. Thank you for committing the fix, I will update the unit test to execute in both big and little endian.
However, it looks like there is one more issue, as reported here for address sanitizer:

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from BTFParserTest
[ RUN      ] BTFParserTest.simpleCorrectInput
/b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp:141:33: runtime error: upcast of misaligned address 0x7facce60411f for type 'llvm::SmallString<0>', which requires 8 byte alignment
0x7facce60411f: note: pointer points here
 64 00 00 00 37  41 60 ce ac 7f 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00
             ^ 
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /b/sanitizer-x86_64-linux-fast/build/llvm-project/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp:141:33 in

Probably because of the attribute "packed" used for too many things:

c++
#pragma pack(push, 1)
struct MockData1 {
  struct B {
    ...
  } BTF;
  struct E {
    ...
  } Ext;

  int BTFSectionLen = sizeof(BTF);
  int ExtSectionLen = sizeof(Ext);

  SmallString<0> Storage;
  std::unique_ptr<ObjectFile> Obj;

}
#pragma pack(pop)

Look like access to unaligned pointers in Storage/Obj causes error on S390.
If so, #pragma directives should be pushed invards to apply only to B and ``E.

I'm not sure what is the best course of action here:

  • revert commit and try to test locally (not sure if I can reproduce in on x86, might try QEMU)
  • push another fix and hope for the best

Do you have any suggestions?

By the way, I have committer rights, so I can handle this cleanup.

The test has good test coverage for the regular code path, but the error code paths need the unittest.
In the worst situation we can remove the unittest and figure out how to make it portable to more configurations, but there is likely no value to revert the functionality part and cause churn to the repository.

The test has good test coverage for the regular code path, but the error code paths need the unittest.

Actually, I think there are test cases for each error message parser can currently produce...

I want to push the patch below to the main branch.
I tested it locally and -Wunaligned-access does catch the issue with Obj and Storage.
What do you think?

diff --git a/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp b/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
index 097d6205adec..041933deb4ec 100644
--- a/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
+++ b/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
@@ -44,11 +44,11 @@ namespace {
 // modified before a call to `makeObj()` to test parser with invalid
 // input, etc.
 
+struct MockData1 {
 // Use "pragma pack" to model .BTF & .BTF.ext sections content using
 // 'struct' objects. This pragma is supported by CLANG, GCC & MSVC,
 // which matters for LLVM CI.
 #pragma pack(push, 1)
-struct MockData1 {
   struct B {
     BTF::Header Header = {};
     // no types
@@ -99,6 +99,7 @@ struct MockData1 {
       Header.LineInfoLen = sizeof(Lines);
     }
   } Ext;
+#pragma pack(pop)
 
   int BTFSectionLen = sizeof(BTF);
   int ExtSectionLen = sizeof(Ext);
@@ -143,7 +144,6 @@ Sections:
     return *Obj.get();
   }
 };
-#pragma pack(pop)
 
 TEST(BTFParserTest, simpleCorrectInput) {
   BTFParser BTF;
diff --git a/llvm/unittests/DebugInfo/BTF/CMakeLists.txt b/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
index b425e46b9f0c..8cd4b793a741 100644
--- a/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
@@ -10,4 +10,11 @@ add_llvm_unittest(DebugInfoBTFTests
 
 target_link_libraries(DebugInfoBTFTests PRIVATE LLVMTestingSupport)
 
+# Packed structures are used in the test. Asan/UBsan can catch
+# unaligned access errors, but such builds take significant time.
+# Use clang's -Wunaligned-access to get a heads-up.
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  set_source_files_properties(BTFParserTest.cpp PROPERTIES COMPILE_FLAGS -Wunaligned-access)
+endif()
+
 set_property(TARGET DebugInfoBTFTests PROPERTY FOLDER "Tests/UnitTests/DebugInfoTests")
glandium added inline comments.
llvm/include/llvm/DebugInfo/BTF/BTFContext.h
39

Our builds are failing here:

In file included from /builds/worker/fetches/llvm-project/llvm/lib/DebugInfo/BTF/BTFContext.cpp:15:
/builds/worker/fetches/llvm-project/llvm/include/llvm/DebugInfo/BTF/BTFContext.h:38:63: error: only virtual member functions can be marked 'override'
  getLineInfoForDataAddress(object::SectionedAddress Address) override;
                                                              ^~~~~~~~

(compiling with clang 13)

glandium added inline comments.Jul 12 2023, 8:57 PM
llvm/include/llvm/DebugInfo/BTF/BTFContext.h
39

Forget it, it's self-inflicted, we have a patch that reverts cead4eceb01b935fae07bf4a7e91911b344d2fec

The test has good test coverage for the regular code path, but the error code paths need the unittest.

Actually, I think there are test cases for each error message parser can currently produce...

I want to push the patch below to the main branch.
I tested it locally and -Wunaligned-access does catch the issue with Obj and Storage.
What do you think?

diff --git a/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp b/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
index 097d6205adec..041933deb4ec 100644
--- a/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
+++ b/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp
@@ -44,11 +44,11 @@ namespace {
 // modified before a call to `makeObj()` to test parser with invalid
 // input, etc.
 
+struct MockData1 {
 // Use "pragma pack" to model .BTF & .BTF.ext sections content using
 // 'struct' objects. This pragma is supported by CLANG, GCC & MSVC,
 // which matters for LLVM CI.
 #pragma pack(push, 1)
-struct MockData1 {
   struct B {
     BTF::Header Header = {};
     // no types
@@ -99,6 +99,7 @@ struct MockData1 {
       Header.LineInfoLen = sizeof(Lines);
     }
   } Ext;
+#pragma pack(pop)
 
   int BTFSectionLen = sizeof(BTF);
   int ExtSectionLen = sizeof(Ext);
@@ -143,7 +144,6 @@ Sections:
     return *Obj.get();
   }
 };
-#pragma pack(pop)
 
 TEST(BTFParserTest, simpleCorrectInput) {
   BTFParser BTF;
diff --git a/llvm/unittests/DebugInfo/BTF/CMakeLists.txt b/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
index b425e46b9f0c..8cd4b793a741 100644
--- a/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/BTF/CMakeLists.txt
@@ -10,4 +10,11 @@ add_llvm_unittest(DebugInfoBTFTests
 
 target_link_libraries(DebugInfoBTFTests PRIVATE LLVMTestingSupport)
 
+# Packed structures are used in the test. Asan/UBsan can catch
+# unaligned access errors, but such builds take significant time.
+# Use clang's -Wunaligned-access to get a heads-up.
+if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  set_source_files_properties(BTFParserTest.cpp PROPERTIES COMPILE_FLAGS -Wunaligned-access)
+endif()
+
 set_property(TARGET DebugInfoBTFTests PROPERTY FOLDER "Tests/UnitTests/DebugInfoTests")

llvm-project is conservative on library/unittest specific cflags. If this #pragma shuffling fixes the issue (-fsanitize=alignment implied by -fsanitize=undefined), push just this part.
-fsanitize=alignment is unrelated to asan.

I opened D155176 with packed attribute shuffling, will commit after pre-merge checks are complete for it.
(Want to make sure that the change does not cause issues with MSVC).