xref: /llvm-project/llvm/unittests/DebugInfo/BTF/BTFParserTest.cpp (revision 75bc20ff899753b100cb875ce703af2348a1d6bb)
1 //===-- SourcePrinter.cpp -  source interleaving utilities ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/BTF/BTFContext.h"
10 #include "llvm/ObjectYAML/YAML.h"
11 #include "llvm/ObjectYAML/yaml2obj.h"
12 #include "llvm/Support/SwapByteOrder.h"
13 #include "llvm/Testing/Support/Error.h"
14 
15 using namespace llvm;
16 using namespace llvm::object;
17 
18 #define LC(Line, Col) ((Line << 10u) | Col)
19 #define ASSERT_SUCCEEDED(E) ASSERT_THAT_ERROR((E), Succeeded())
20 
21 const char BTFEndOfData[] =
22     "error while reading .BTF section: unexpected end of data";
23 const char BTFExtEndOfData[] =
24     "error while reading .BTF.ext section: unexpected end of data";
25 
operator <<(raw_ostream & OS,const yaml::BinaryRef & Ref)26 static raw_ostream &operator<<(raw_ostream &OS, const yaml::BinaryRef &Ref) {
27   Ref.writeAsHex(OS);
28   return OS;
29 }
30 
31 template <typename T>
makeBinRef(const T * Ptr,size_t Size=sizeof (T))32 static yaml::BinaryRef makeBinRef(const T *Ptr, size_t Size = sizeof(T)) {
33   return yaml::BinaryRef(ArrayRef<uint8_t>((const uint8_t *)Ptr, Size));
34 }
35 
36 namespace {
37 // This is a mockup for an ELF file containing .BTF and .BTF.ext sections.
38 // Binary content of these sections corresponds to the value of
39 // MockData1::BTF and MockData1::Ext fields.
40 //
41 // The yaml::yaml2ObjectFile() is used to generate actual ELF,
42 // see MockData1::makeObj().
43 //
44 // The `BTF` and `Ext` fields are initialized with correct values
45 // valid for a small example with a few sections, fields could be
46 // modified before a call to `makeObj()` to test parser with invalid
47 // input, etc.
48 
49 struct MockData1 {
50 // Use "pragma pack" to model .BTF & .BTF.ext sections content using
51 // 'struct' objects. This pragma is supported by CLANG, GCC & MSVC,
52 // which matters for LLVM CI.
53 #pragma pack(push, 1)
54   struct B {
55     BTF::Header Header = {};
56     // No types.
57     struct S {
58       char Foo[4] = "foo";
59       char Bar[4] = "bar";
60       char Buz[4] = "buz";
61       char Line1[11] = "first line";
62       char Line2[12] = "second line";
63       char File1[4] = "a.c";
64       char File2[4] = "b.c";
65     } Strings;
66 
B__anon10cc3c150111::MockData1::B67     B() {
68       Header.Magic = BTF::MAGIC;
69       Header.Version = 1;
70       Header.HdrLen = sizeof(Header);
71       Header.StrOff = offsetof(B, Strings) - sizeof(Header);
72       Header.StrLen = sizeof(Strings);
73     }
74   } BTF;
75 
76   struct E {
77     BTF::ExtHeader Header = {};
78     // No func info.
79     struct {
80       uint32_t LineRecSize = sizeof(BTF::BPFLineInfo);
81       struct {
82         BTF::SecLineInfo Sec = {offsetof(B::S, Foo), 2};
83         BTF::BPFLineInfo Lines[2] = {
84             {16, offsetof(B::S, File1), offsetof(B::S, Line1), LC(7, 1)},
85             {32, offsetof(B::S, File1), offsetof(B::S, Line2), LC(14, 5)},
86         };
87       } Foo;
88       struct {
89         BTF::SecLineInfo Sec = {offsetof(B::S, Bar), 1};
90         BTF::BPFLineInfo Lines[1] = {
91             {0, offsetof(B::S, File2), offsetof(B::S, Line1), LC(42, 4)},
92         };
93       } Bar;
94     } Lines;
95 
E__anon10cc3c150111::MockData1::E96     E() {
97       Header.Magic = BTF::MAGIC;
98       Header.Version = 1;
99       Header.HdrLen = sizeof(Header);
100       Header.LineInfoOff = offsetof(E, Lines) - sizeof(Header);
101       Header.LineInfoLen = sizeof(Lines);
102     }
103   } Ext;
104 #pragma pack(pop)
105 
106   int BTFSectionLen = sizeof(BTF);
107   int ExtSectionLen = sizeof(Ext);
108 
109   SmallString<0> Storage;
110   std::unique_ptr<ObjectFile> Obj;
111 
makeObj__anon10cc3c150111::MockData1112   ObjectFile &makeObj() {
113     std::string Buffer;
114     raw_string_ostream Yaml(Buffer);
115     Yaml << R"(
116 !ELF
117 FileHeader:
118   Class:    ELFCLASS64)";
119     if (sys::IsBigEndianHost)
120       Yaml << "\n  Data:     ELFDATA2MSB";
121     else
122       Yaml << "\n  Data:     ELFDATA2LSB";
123     Yaml << R"(
124   Type:     ET_REL
125   Machine:  EM_BPF
126 Sections:
127   - Name:     foo
128     Type:     SHT_PROGBITS
129     Size:     0x0
130   - Name:     bar
131     Type:     SHT_PROGBITS
132     Size:     0x0)";
133 
134     if (BTFSectionLen >= 0)
135       Yaml << R"(
136   - Name:     .BTF
137     Type:     SHT_PROGBITS
138     Content: )"
139            << makeBinRef(&BTF, BTFSectionLen);
140 
141     if (ExtSectionLen >= 0)
142       Yaml << R"(
143   - Name:     .BTF.ext
144     Type:     SHT_PROGBITS
145     Content: )"
146            << makeBinRef(&Ext, ExtSectionLen);
147 
148     Obj = yaml::yaml2ObjectFile(Storage, Buffer,
149                                 [](const Twine &Err) { errs() << Err; });
150     return *Obj;
151   }
152 };
153 
TEST(BTFParserTest,simpleCorrectInput)154 TEST(BTFParserTest, simpleCorrectInput) {
155   BTFParser BTF;
156   MockData1 Mock;
157   Error Err = BTF.parse(Mock.makeObj());
158   EXPECT_FALSE(Err);
159 
160   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, Foo)), "foo");
161   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, Bar)), "bar");
162   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, Line1)), "first line");
163   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, Line2)), "second line");
164   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, File1)), "a.c");
165   EXPECT_EQ(BTF.findString(offsetof(MockData1::B::S, File2)), "b.c");
166 
167   // Invalid offset.
168   EXPECT_EQ(BTF.findString(sizeof(MockData1::B::S)), StringRef());
169 
170   const BTF::BPFLineInfo *I1 = BTF.findLineInfo({16, 1});
171   ASSERT_TRUE(I1);
172   EXPECT_EQ(I1->getLine(), 7u);
173   EXPECT_EQ(I1->getCol(), 1u);
174   EXPECT_EQ(BTF.findString(I1->FileNameOff), "a.c");
175   EXPECT_EQ(BTF.findString(I1->LineOff), "first line");
176 
177   const BTF::BPFLineInfo *I2 = BTF.findLineInfo({32, 1});
178   ASSERT_TRUE(I2);
179   EXPECT_EQ(I2->getLine(), 14u);
180   EXPECT_EQ(I2->getCol(), 5u);
181   EXPECT_EQ(BTF.findString(I2->FileNameOff), "a.c");
182   EXPECT_EQ(BTF.findString(I2->LineOff), "second line");
183 
184   const BTF::BPFLineInfo *I3 = BTF.findLineInfo({0, 2});
185   ASSERT_TRUE(I3);
186   EXPECT_EQ(I3->getLine(), 42u);
187   EXPECT_EQ(I3->getCol(), 4u);
188   EXPECT_EQ(BTF.findString(I3->FileNameOff), "b.c");
189   EXPECT_EQ(BTF.findString(I3->LineOff), "first line");
190 
191   // No info for insn address.
192   EXPECT_FALSE(BTF.findLineInfo({24, 1}));
193   EXPECT_FALSE(BTF.findLineInfo({8, 2}));
194   // No info for section number.
195   EXPECT_FALSE(BTF.findLineInfo({16, 3}));
196 }
197 
TEST(BTFParserTest,badSectionNameOffset)198 TEST(BTFParserTest, badSectionNameOffset) {
199   BTFParser BTF;
200   MockData1 Mock;
201   // "foo" is section #1, corrupting it's name offset will make impossible
202   // to match section name with section index when BTF is parsed.
203   Mock.Ext.Lines.Foo.Sec.SecNameOff = 100500;
204   Error Err = BTF.parse(Mock.makeObj());
205   EXPECT_FALSE(Err);
206   // "foo" line info should be corrupted.
207   EXPECT_FALSE(BTF.findLineInfo({16, 1}));
208   // "bar" line info should be ok.
209   EXPECT_TRUE(BTF.findLineInfo({0, 2}));
210 }
211 
212 // Keep this as macro to preserve line number info.
213 #define EXPECT_PARSE_ERROR(Mock, Message)                                      \
214   do {                                                                         \
215     BTFParser BTF;                                                             \
216     EXPECT_THAT_ERROR(BTF.parse((Mock).makeObj()),                             \
217                       FailedWithMessage(testing::HasSubstr(Message)));         \
218   } while (false)
219 
TEST(BTFParserTest,badBTFMagic)220 TEST(BTFParserTest, badBTFMagic) {
221   MockData1 Mock;
222   Mock.BTF.Header.Magic = 42;
223   EXPECT_PARSE_ERROR(Mock, "invalid .BTF magic: 2a");
224 }
225 
TEST(BTFParserTest,badBTFVersion)226 TEST(BTFParserTest, badBTFVersion) {
227   MockData1 Mock;
228   Mock.BTF.Header.Version = 42;
229   EXPECT_PARSE_ERROR(Mock, "unsupported .BTF version: 42");
230 }
231 
TEST(BTFParserTest,badBTFHdrLen)232 TEST(BTFParserTest, badBTFHdrLen) {
233   MockData1 Mock;
234   Mock.BTF.Header.HdrLen = 5;
235   EXPECT_PARSE_ERROR(Mock, "unexpected .BTF header length: 5");
236 }
237 
TEST(BTFParserTest,badBTFSectionLen)238 TEST(BTFParserTest, badBTFSectionLen) {
239   MockData1 Mock1, Mock2;
240 
241   // Cut-off string section by one byte.
242   Mock1.BTFSectionLen =
243       offsetof(MockData1::B, Strings) + sizeof(MockData1::B::S) - 1;
244   EXPECT_PARSE_ERROR(Mock1, "invalid .BTF section size");
245 
246   // Cut-off header.
247   Mock2.BTFSectionLen = offsetof(BTF::Header, StrOff);
248   EXPECT_PARSE_ERROR(Mock2, BTFEndOfData);
249 }
250 
TEST(BTFParserTest,badBTFExtMagic)251 TEST(BTFParserTest, badBTFExtMagic) {
252   MockData1 Mock;
253   Mock.Ext.Header.Magic = 42;
254   EXPECT_PARSE_ERROR(Mock, "invalid .BTF.ext magic: 2a");
255 }
256 
TEST(BTFParserTest,badBTFExtVersion)257 TEST(BTFParserTest, badBTFExtVersion) {
258   MockData1 Mock;
259   Mock.Ext.Header.Version = 42;
260   EXPECT_PARSE_ERROR(Mock, "unsupported .BTF.ext version: 42");
261 }
262 
TEST(BTFParserTest,badBTFExtHdrLen)263 TEST(BTFParserTest, badBTFExtHdrLen) {
264   MockData1 Mock1, Mock2;
265 
266   Mock1.Ext.Header.HdrLen = 5;
267   EXPECT_PARSE_ERROR(Mock1, "unexpected .BTF.ext header length: 5");
268 
269   Mock2.Ext.Header.HdrLen = sizeof(Mock2.Ext);
270   EXPECT_PARSE_ERROR(Mock2, BTFExtEndOfData);
271 }
272 
TEST(BTFParserTest,badBTFExtSectionLen)273 TEST(BTFParserTest, badBTFExtSectionLen) {
274   MockData1 Mock1, Mock2, Mock3;
275 
276   // Cut-off header before HdrLen.
277   Mock1.ExtSectionLen = offsetof(BTF::ExtHeader, HdrLen);
278   EXPECT_PARSE_ERROR(Mock1, BTFExtEndOfData);
279 
280   // Cut-off header before LineInfoLen.
281   Mock2.ExtSectionLen = offsetof(BTF::ExtHeader, LineInfoLen);
282   EXPECT_PARSE_ERROR(Mock2, BTFExtEndOfData);
283 
284   // Cut-off line-info section somewhere in the middle.
285   Mock3.ExtSectionLen = offsetof(MockData1::E, Lines) + 4;
286   EXPECT_PARSE_ERROR(Mock3, BTFExtEndOfData);
287 }
288 
TEST(BTFParserTest,badBTFExtLineInfoRecSize)289 TEST(BTFParserTest, badBTFExtLineInfoRecSize) {
290   MockData1 Mock1, Mock2;
291 
292   Mock1.Ext.Lines.LineRecSize = 2;
293   EXPECT_PARSE_ERROR(Mock1, "unexpected .BTF.ext line info record length: 2");
294 
295   Mock2.Ext.Lines.LineRecSize = sizeof(Mock2.Ext.Lines.Foo.Lines[0]) + 1;
296   EXPECT_PARSE_ERROR(Mock2, BTFExtEndOfData);
297 }
298 
TEST(BTFParserTest,badBTFExtLineSectionName)299 TEST(BTFParserTest, badBTFExtLineSectionName) {
300   MockData1 Mock1;
301 
302   Mock1.Ext.Lines.Foo.Sec.SecNameOff = offsetof(MockData1::B::S, Buz);
303   EXPECT_PARSE_ERROR(
304       Mock1, "can't find section 'buz' while parsing .BTF.ext line info");
305 }
306 
TEST(BTFParserTest,missingSections)307 TEST(BTFParserTest, missingSections) {
308   MockData1 Mock1, Mock2, Mock3;
309 
310   Mock1.BTFSectionLen = -1;
311   EXPECT_PARSE_ERROR(Mock1, "can't find .BTF section");
312   EXPECT_FALSE(BTFParser::hasBTFSections(Mock1.makeObj()));
313 
314   Mock2.ExtSectionLen = -1;
315   EXPECT_PARSE_ERROR(Mock2, "can't find .BTF.ext section");
316   EXPECT_FALSE(BTFParser::hasBTFSections(Mock2.makeObj()));
317 
318   EXPECT_TRUE(BTFParser::hasBTFSections(Mock3.makeObj()));
319 }
320 
321 // Check that BTFParser instance is reset when BTFParser::parse() is
322 // called several times.
TEST(BTFParserTest,parserReset)323 TEST(BTFParserTest, parserReset) {
324   BTFParser BTF;
325   MockData1 Mock1, Mock2;
326 
327   EXPECT_FALSE(BTF.parse(Mock1.makeObj()));
328   EXPECT_TRUE(BTF.findLineInfo({16, 1}));
329   EXPECT_TRUE(BTF.findLineInfo({0, 2}));
330 
331   // Break the reference to "bar" section name, thus making
332   // information about "bar" line numbers unavailable.
333   Mock2.Ext.Lines.Bar.Sec.SecNameOff = 100500;
334 
335   EXPECT_FALSE(BTF.parse(Mock2.makeObj()));
336   EXPECT_TRUE(BTF.findLineInfo({16, 1}));
337   // Make sure that "bar" no longer available (its index is 2).
338   EXPECT_FALSE(BTF.findLineInfo({0, 2}));
339 }
340 
TEST(BTFParserTest,btfContext)341 TEST(BTFParserTest, btfContext) {
342   MockData1 Mock;
343   BTFParser BTF;
344   std::unique_ptr<BTFContext> Ctx = BTFContext::create(Mock.makeObj());
345 
346   DILineInfo I1 = Ctx->getLineInfoForAddress({16, 1});
347   EXPECT_EQ(I1.Line, 7u);
348   EXPECT_EQ(I1.Column, 1u);
349   EXPECT_EQ(I1.FileName, "a.c");
350   EXPECT_EQ(I1.LineSource, "first line");
351 
352   DILineInfo I2 = Ctx->getLineInfoForAddress({24, 1});
353   EXPECT_EQ(I2.Line, 0u);
354   EXPECT_EQ(I2.Column, 0u);
355   EXPECT_EQ(I2.FileName, DILineInfo::BadString);
356   EXPECT_EQ(I2.LineSource, std::nullopt);
357 }
358 
mkInfo(uint32_t Kind)359 static uint32_t mkInfo(uint32_t Kind) { return Kind << 24; }
360 
append(std::string & S,const T & What)361 template <typename T> static void append(std::string &S, const T &What) {
362   S.append((const char *)&What, sizeof(What));
363 }
364 
365 class MockData2 {
366   SmallString<0> ObjStorage;
367   std::unique_ptr<ObjectFile> Obj;
368   std::string Types;
369   std::string Strings;
370   std::string Relocs;
371   std::string Lines;
372   unsigned TotalTypes;
373   int LastRelocSecIdx;
374   unsigned NumRelocs;
375   int LastLineSecIdx;
376   unsigned NumLines;
377 
378 public:
MockData2()379   MockData2() { reset(); }
380 
totalTypes() const381   unsigned totalTypes() const { return TotalTypes; }
382 
addString(StringRef S)383   uint32_t addString(StringRef S) {
384     uint32_t Off = Strings.size();
385     Strings.append(S.data(), S.size());
386     Strings.append("\0", 1);
387     return Off;
388   };
389 
addType(const BTF::CommonType & Tp)390   uint32_t addType(const BTF::CommonType &Tp) {
391     append(Types, Tp);
392     return ++TotalTypes;
393   }
394 
addTail(const T & Tp)395   template <typename T> void addTail(const T &Tp) { append(Types, Tp); }
396 
resetTypes()397   void resetTypes() {
398     Types.resize(0);
399     TotalTypes = 0;
400   }
401 
reset()402   void reset() {
403     ObjStorage.clear();
404     Types.resize(0);
405     Strings.resize(0);
406     Relocs.resize(0);
407     Lines.resize(0);
408     TotalTypes = 0;
409     LastRelocSecIdx = -1;
410     NumRelocs = 0;
411     LastLineSecIdx = -1;
412     NumLines = 0;
413   }
414 
finishRelocSec()415   void finishRelocSec() {
416     if (LastRelocSecIdx == -1)
417       return;
418 
419     BTF::SecFieldReloc *SecInfo =
420         (BTF::SecFieldReloc *)&Relocs[LastRelocSecIdx];
421     SecInfo->NumFieldReloc = NumRelocs;
422     LastRelocSecIdx = -1;
423     NumRelocs = 0;
424   }
425 
finishLineSec()426   void finishLineSec() {
427     if (LastLineSecIdx == -1)
428       return;
429 
430     BTF::SecLineInfo *SecInfo = (BTF::SecLineInfo *)&Lines[LastLineSecIdx];
431     SecInfo->NumLineInfo = NumLines;
432     NumLines = 0;
433     LastLineSecIdx = -1;
434   }
435 
addRelocSec(const BTF::SecFieldReloc & R)436   void addRelocSec(const BTF::SecFieldReloc &R) {
437     finishRelocSec();
438     LastRelocSecIdx = Relocs.size();
439     append(Relocs, R);
440   }
441 
addReloc(const BTF::BPFFieldReloc & R)442   void addReloc(const BTF::BPFFieldReloc &R) {
443     append(Relocs, R);
444     ++NumRelocs;
445   }
446 
addLinesSec(const BTF::SecLineInfo & R)447   void addLinesSec(const BTF::SecLineInfo &R) {
448     finishLineSec();
449     LastLineSecIdx = Lines.size();
450     append(Lines, R);
451   }
452 
addLine(const BTF::BPFLineInfo & R)453   void addLine(const BTF::BPFLineInfo &R) {
454     append(Lines, R);
455     ++NumLines;
456   }
457 
makeObj()458   ObjectFile &makeObj() {
459     finishRelocSec();
460     finishLineSec();
461 
462     BTF::Header BTFHeader = {};
463     BTFHeader.Magic = BTF::MAGIC;
464     BTFHeader.Version = 1;
465     BTFHeader.HdrLen = sizeof(BTFHeader);
466     BTFHeader.StrOff = 0;
467     BTFHeader.StrLen = Strings.size();
468     BTFHeader.TypeOff = Strings.size();
469     BTFHeader.TypeLen = Types.size();
470 
471     std::string BTFSec;
472     append(BTFSec, BTFHeader);
473     BTFSec.append(Strings);
474     BTFSec.append(Types);
475 
476     BTF::ExtHeader ExtHeader = {};
477     ExtHeader.Magic = BTF::MAGIC;
478     ExtHeader.Version = 1;
479     ExtHeader.HdrLen = sizeof(ExtHeader);
480     ExtHeader.FieldRelocOff = 0;
481     ExtHeader.FieldRelocLen = Relocs.size() + sizeof(uint32_t);
482     ExtHeader.LineInfoOff = ExtHeader.FieldRelocLen;
483     ExtHeader.LineInfoLen = Lines.size() + sizeof(uint32_t);
484 
485     std::string ExtSec;
486     append(ExtSec, ExtHeader);
487     append(ExtSec, (uint32_t)sizeof(BTF::BPFFieldReloc));
488     ExtSec.append(Relocs);
489     append(ExtSec, (uint32_t)sizeof(BTF::BPFLineInfo));
490     ExtSec.append(Lines);
491 
492     std::string YamlBuffer;
493     raw_string_ostream Yaml(YamlBuffer);
494     Yaml << R"(
495 !ELF
496 FileHeader:
497   Class:    ELFCLASS64)";
498     if (sys::IsBigEndianHost)
499       Yaml << "\n  Data:     ELFDATA2MSB";
500     else
501       Yaml << "\n  Data:     ELFDATA2LSB";
502     Yaml << R"(
503   Type:     ET_REL
504   Machine:  EM_BPF
505 Sections:
506   - Name:     foo
507     Type:     SHT_PROGBITS
508     Size:     0x80
509   - Name:     bar
510     Type:     SHT_PROGBITS
511     Size:     0x80
512   - Name:     .BTF
513     Type:     SHT_PROGBITS
514     Content: )"
515          << makeBinRef(BTFSec.data(), BTFSec.size());
516     Yaml << R"(
517   - Name:     .BTF.ext
518     Type:     SHT_PROGBITS
519     Content: )"
520          << makeBinRef(ExtSec.data(), ExtSec.size());
521 
522     Obj = yaml::yaml2ObjectFile(ObjStorage, YamlBuffer,
523                                 [](const Twine &Err) { errs() << Err; });
524     return *Obj;
525   }
526 };
527 
TEST(BTFParserTest,allTypeKinds)528 TEST(BTFParserTest, allTypeKinds) {
529   MockData2 D;
530   D.addType({D.addString("1"), mkInfo(BTF::BTF_KIND_INT), {4}});
531   D.addTail((uint32_t)0);
532   D.addType({D.addString("2"), mkInfo(BTF::BTF_KIND_PTR), {1}});
533   D.addType({D.addString("3"), mkInfo(BTF::BTF_KIND_ARRAY), {0}});
534   D.addTail(BTF::BTFArray({1, 1, 2}));
535   D.addType({D.addString("4"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});
536   D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));
537   D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));
538   D.addType({D.addString("5"), mkInfo(BTF::BTF_KIND_UNION) | 3, {8}});
539   D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));
540   D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));
541   D.addTail(BTF::BTFMember({D.addString("c"), 1, 0}));
542   D.addType({D.addString("6"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});
543   D.addTail(BTF::BTFEnum({D.addString("U"), 1}));
544   D.addTail(BTF::BTFEnum({D.addString("V"), 2}));
545   D.addType({D.addString("7"), mkInfo(BTF::BTF_KIND_ENUM64) | 1, {4}});
546   D.addTail(BTF::BTFEnum64({D.addString("W"), 0, 1}));
547   D.addType(
548       {D.addString("8"), BTF::FWD_UNION_FLAG | mkInfo(BTF::BTF_KIND_FWD), {0}});
549   D.addType({D.addString("9"), mkInfo(BTF::BTF_KIND_TYPEDEF), {1}});
550   D.addType({D.addString("10"), mkInfo(BTF::BTF_KIND_VOLATILE), {1}});
551   D.addType({D.addString("11"), mkInfo(BTF::BTF_KIND_CONST), {1}});
552   D.addType({D.addString("12"), mkInfo(BTF::BTF_KIND_RESTRICT), {1}});
553   D.addType({D.addString("13"), mkInfo(BTF::BTF_KIND_FUNC_PROTO) | 1, {1}});
554   D.addTail(BTF::BTFParam({D.addString("P"), 2}));
555   D.addType({D.addString("14"), mkInfo(BTF::BTF_KIND_FUNC), {13}});
556   D.addType({D.addString("15"), mkInfo(BTF::BTF_KIND_VAR), {2}});
557   D.addTail((uint32_t)0);
558   D.addType({D.addString("16"), mkInfo(BTF::BTF_KIND_DATASEC) | 3, {0}});
559   D.addTail(BTF::BTFDataSec({1, 0, 4}));
560   D.addTail(BTF::BTFDataSec({1, 4, 4}));
561   D.addTail(BTF::BTFDataSec({1, 8, 4}));
562   D.addType({D.addString("17"), mkInfo(BTF::BTF_KIND_FLOAT), {4}});
563   D.addType({D.addString("18"), mkInfo(BTF::BTF_KIND_DECL_TAG), {0}});
564   D.addTail((uint32_t)-1);
565   D.addType({D.addString("19"), mkInfo(BTF::BTF_KIND_TYPE_TAG), {0}});
566 
567   BTFParser BTF;
568   Error Err = BTF.parse(D.makeObj());
569   EXPECT_FALSE(Err);
570 
571   EXPECT_EQ(D.totalTypes() + 1 /* +1 for void */, BTF.typesCount());
572   for (unsigned Id = 1; Id < D.totalTypes() + 1; ++Id) {
573     const BTF::CommonType *Tp = BTF.findType(Id);
574     ASSERT_TRUE(Tp);
575     std::string IdBuf;
576     raw_string_ostream IdBufStream(IdBuf);
577     IdBufStream << Id;
578     EXPECT_EQ(BTF.findString(Tp->NameOff), IdBuf);
579   }
580 }
581 
TEST(BTFParserTest,bigStruct)582 TEST(BTFParserTest, bigStruct) {
583   const uint32_t N = 1000u;
584   MockData2 D;
585   uint32_t FStr = D.addString("f");
586   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_INT), {4}});
587   D.addTail((uint32_t)0);
588   D.addType({D.addString("big"), mkInfo(BTF::BTF_KIND_STRUCT) | N, {8}});
589   for (unsigned I = 0; I < N; ++I)
590     D.addTail(BTF::BTFMember({FStr, 1, 0}));
591   D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_INT), {4}});
592   D.addTail((uint32_t)0);
593 
594   BTFParser BTF;
595   ASSERT_SUCCEEDED(BTF.parse(D.makeObj()));
596   ASSERT_EQ(BTF.typesCount(), 4u /* +1 for void */);
597   const BTF::CommonType *Foo = BTF.findType(1);
598   const BTF::CommonType *Big = BTF.findType(2);
599   const BTF::CommonType *Bar = BTF.findType(3);
600   ASSERT_TRUE(Foo);
601   ASSERT_TRUE(Big);
602   ASSERT_TRUE(Bar);
603   EXPECT_EQ(BTF.findString(Foo->NameOff), "foo");
604   EXPECT_EQ(BTF.findString(Big->NameOff), "big");
605   EXPECT_EQ(BTF.findString(Bar->NameOff), "bar");
606   EXPECT_EQ(Big->getVlen(), N);
607 }
608 
TEST(BTFParserTest,incompleteTypes)609 TEST(BTFParserTest, incompleteTypes) {
610   MockData2 D;
611   auto IncompleteType = [&](const BTF::CommonType &Tp) {
612     D.resetTypes();
613     D.addType(Tp);
614     EXPECT_PARSE_ERROR(D, "incomplete type definition in .BTF section");
615   };
616 
617   // All kinds that need tail.
618   IncompleteType({D.addString("a"), mkInfo(BTF::BTF_KIND_INT), {4}});
619   IncompleteType({D.addString("b"), mkInfo(BTF::BTF_KIND_ARRAY), {0}});
620   IncompleteType({D.addString("c"), mkInfo(BTF::BTF_KIND_VAR), {0}});
621   IncompleteType({D.addString("d"), mkInfo(BTF::BTF_KIND_DECL_TAG), {0}});
622 
623   // All kinds with vlen.
624   IncompleteType({D.addString("a"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});
625   IncompleteType({D.addString("b"), mkInfo(BTF::BTF_KIND_UNION) | 3, {8}});
626   IncompleteType({D.addString("c"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});
627   IncompleteType({D.addString("d"), mkInfo(BTF::BTF_KIND_ENUM64) | 1, {4}});
628   IncompleteType({D.addString("e"), mkInfo(BTF::BTF_KIND_FUNC_PROTO) | 1, {1}});
629   IncompleteType({D.addString("f"), mkInfo(BTF::BTF_KIND_DATASEC) | 3, {0}});
630 
631   // An unexpected tail.
632   D.resetTypes();
633   D.addTail((uint32_t)0);
634   EXPECT_PARSE_ERROR(D, "incomplete type definition in .BTF section");
635 }
636 
637 // Use macro to preserve line number in error message.
638 #define SYMBOLIZE(SecAddr, Expected)                                           \
639   do {                                                                         \
640     const BTF::BPFFieldReloc *R = BTF.findFieldReloc((SecAddr));               \
641     ASSERT_TRUE(R);                                                            \
642     SmallString<64> Symbolized;                                                \
643     BTF.symbolize(R, Symbolized);                                              \
644     EXPECT_EQ(Symbolized, (Expected));                                         \
645   } while (false)
646 
647 // Shorter name for initializers below.
648 using SA = SectionedAddress;
649 
TEST(BTFParserTest,typeRelocs)650 TEST(BTFParserTest, typeRelocs) {
651   MockData2 D;
652   uint32_t Zero = D.addString("0");
653   // id 1: struct foo {}
654   // id 2: union bar;
655   // id 3: struct buz;
656   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
657   D.addType({D.addString("bar"),
658              mkInfo(BTF::BTF_KIND_FWD) | BTF::FWD_UNION_FLAG,
659              {0}});
660   D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_FWD), {0}});
661   D.addRelocSec({D.addString("foo"), 7});
662   // List of all possible correct type relocations for type id #1.
663   D.addReloc({0, 1, Zero, BTF::BTF_TYPE_ID_LOCAL});
664   D.addReloc({8, 1, Zero, BTF::BTF_TYPE_ID_REMOTE});
665   D.addReloc({16, 1, Zero, BTF::TYPE_EXISTENCE});
666   D.addReloc({24, 1, Zero, BTF::TYPE_MATCH});
667   D.addReloc({32, 1, Zero, BTF::TYPE_SIZE});
668   // Forward declarations.
669   D.addReloc({40, 2, Zero, BTF::TYPE_SIZE});
670   D.addReloc({48, 3, Zero, BTF::TYPE_SIZE});
671   // Incorrect type relocation: bad type id.
672   D.addReloc({56, 42, Zero, BTF::TYPE_SIZE});
673   // Incorrect type relocation: spec should be '0'.
674   D.addReloc({64, 1, D.addString("10"), BTF::TYPE_SIZE});
675 
676   BTFParser BTF;
677   Error E = BTF.parse(D.makeObj());
678   EXPECT_FALSE(E);
679 
680   SYMBOLIZE(SA({0, 1}), "<local_type_id> [1] struct foo");
681   SYMBOLIZE(SA({8, 1}), "<target_type_id> [1] struct foo");
682   SYMBOLIZE(SA({16, 1}), "<type_exists> [1] struct foo");
683   SYMBOLIZE(SA({24, 1}), "<type_matches> [1] struct foo");
684   SYMBOLIZE(SA({32, 1}), "<type_size> [1] struct foo");
685   SYMBOLIZE(SA({40, 1}), "<type_size> [2] fwd union bar");
686   SYMBOLIZE(SA({48, 1}), "<type_size> [3] fwd struct buz");
687   SYMBOLIZE(SA({56, 1}), "<type_size> [42] '0' <unknown type id: 42>");
688   SYMBOLIZE(SA({64, 1}),
689             "<type_size> [1] '10' "
690             "<unexpected type-based relocation spec: should be '0'>");
691 }
692 
TEST(BTFParserTest,enumRelocs)693 TEST(BTFParserTest, enumRelocs) {
694   MockData2 D;
695   // id 1: enum { U, V }
696   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});
697   D.addTail(BTF::BTFEnum({D.addString("U"), 1}));
698   D.addTail(BTF::BTFEnum({D.addString("V"), 2}));
699   // id 2: int
700   D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});
701   D.addTail((uint32_t)0);
702   // id 3: enum: uint64_t { A, B }
703   D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_ENUM64) | 2, {8}});
704   D.addTail(BTF::BTFEnum64({D.addString("A"), 1, 0}));
705   D.addTail(BTF::BTFEnum64({D.addString("B"), 2, 0}));
706 
707   D.addRelocSec({D.addString("foo"), 5});
708   // An ok relocation accessing value #1: U.
709   D.addReloc({0, 1, D.addString("0"), BTF::ENUM_VALUE_EXISTENCE});
710   // An ok relocation accessing value #2: V.
711   D.addReloc({8, 1, D.addString("1"), BTF::ENUM_VALUE});
712   // Incorrect relocation: too many elements in string "1:0".
713   D.addReloc({16, 1, D.addString("1:0"), BTF::ENUM_VALUE});
714   // Incorrect relocation: type id "2" is not an enum.
715   D.addReloc({24, 2, D.addString("1"), BTF::ENUM_VALUE});
716   // Incorrect relocation: value #42 does not exist for enum "foo".
717   D.addReloc({32, 1, D.addString("42"), BTF::ENUM_VALUE});
718   // An ok relocation accessing value #1: A.
719   D.addReloc({40, 3, D.addString("0"), BTF::ENUM_VALUE_EXISTENCE});
720   // An ok relocation accessing value #2: B.
721   D.addReloc({48, 3, D.addString("1"), BTF::ENUM_VALUE});
722 
723   BTFParser BTF;
724   Error E = BTF.parse(D.makeObj());
725   EXPECT_FALSE(E);
726 
727   SYMBOLIZE(SA({0, 1}), "<enumval_exists> [1] enum foo::U = 1");
728   SYMBOLIZE(SA({8, 1}), "<enumval_value> [1] enum foo::V = 2");
729   SYMBOLIZE(
730       SA({16, 1}),
731       "<enumval_value> [1] '1:0' <unexpected enumval relocation spec size>");
732   SYMBOLIZE(
733       SA({24, 1}),
734       "<enumval_value> [2] '1' <unexpected type kind for enum relocation: 1>");
735   SYMBOLIZE(SA({32, 1}), "<enumval_value> [1] '42' <bad value index: 42>");
736   SYMBOLIZE(SA({40, 1}), "<enumval_exists> [3] enum bar::A = 1");
737   SYMBOLIZE(SA({48, 1}), "<enumval_value> [3] enum bar::B = 2");
738 }
739 
TEST(BTFParserTest,enumRelocsMods)740 TEST(BTFParserTest, enumRelocsMods) {
741   MockData2 D;
742   // id 1: enum { U, V }
743   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});
744   D.addTail(BTF::BTFEnum({D.addString("U"), 1}));
745   D.addTail(BTF::BTFEnum({D.addString("V"), 2}));
746   // id 2: typedef enum foo a;
747   D.addType({D.addString("a"), mkInfo(BTF::BTF_KIND_TYPEDEF), {1}});
748   // id 3: const enum foo;
749   D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {1}});
750 
751   D.addRelocSec({D.addString("foo"), 0});
752   D.addReloc({0, 2, D.addString("0"), BTF::ENUM_VALUE});
753   D.addReloc({8, 3, D.addString("1"), BTF::ENUM_VALUE});
754 
755   BTFParser BTF;
756   Error E = BTF.parse(D.makeObj());
757   EXPECT_FALSE(E);
758 
759   SYMBOLIZE(SA({0, 1}), "<enumval_value> [2] typedef a::U = 1");
760   SYMBOLIZE(SA({8, 1}), "<enumval_value> [3] const enum foo::V = 2");
761 }
762 
TEST(BTFParserTest,fieldRelocs)763 TEST(BTFParserTest, fieldRelocs) {
764   MockData2 D;
765   // id 1: int
766   D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});
767   D.addTail((uint32_t)0);
768   // id 2: struct foo { int a; int b; }
769   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});
770   D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));
771   D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));
772   // id 3: array of struct foo.
773   D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_ARRAY), {0}});
774   D.addTail(BTF::BTFArray({2, 1, 2}));
775   // id 4: struct bar { struct foo u[2]; int v; }
776   D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});
777   D.addTail(BTF::BTFMember({D.addString("u"), 3, 0}));
778   D.addTail(BTF::BTFMember({D.addString("v"), 1, 0}));
779   // id 5: array with bad element type id.
780   D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_ARRAY), {0}});
781   D.addTail(BTF::BTFArray({42, 1, 2}));
782   // id 6: struct buz { <bad type> u[2]; <bad type> v; }
783   D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});
784   D.addTail(BTF::BTFMember({D.addString("u"), 5, 0}));
785   D.addTail(BTF::BTFMember({D.addString("v"), 42, 0}));
786 
787   D.addRelocSec({D.addString("foo"), 0 /* patched automatically */});
788   // All field relocations kinds for struct bar::v.
789   D.addReloc({0, 4, D.addString("0:1"), BTF::FIELD_BYTE_OFFSET});
790   D.addReloc({8, 4, D.addString("0:1"), BTF::FIELD_BYTE_SIZE});
791   D.addReloc({16, 4, D.addString("0:1"), BTF::FIELD_EXISTENCE});
792   D.addReloc({24, 4, D.addString("0:1"), BTF::FIELD_SIGNEDNESS});
793   D.addReloc({32, 4, D.addString("0:1"), BTF::FIELD_LSHIFT_U64});
794   D.addReloc({40, 4, D.addString("0:1"), BTF::FIELD_RSHIFT_U64});
795   // Non-zero first idx.
796   D.addReloc({48, 4, D.addString("7:1"), BTF::FIELD_BYTE_OFFSET});
797   // Access through array and struct: struct bar::u[1].a.
798   D.addReloc({56, 4, D.addString("0:0:1:0"), BTF::FIELD_BYTE_OFFSET});
799   // Access through array and struct: struct bar::u[1].b.
800   D.addReloc({64, 4, D.addString("0:0:1:1"), BTF::FIELD_BYTE_OFFSET});
801   // Incorrect relocation: empty access string.
802   D.addReloc({72, 4, D.addString(""), BTF::FIELD_BYTE_OFFSET});
803   // Incorrect relocation: member index out of range (only two members in bar).
804   D.addReloc({80, 4, D.addString("0:2"), BTF::FIELD_BYTE_OFFSET});
805   // Incorrect relocation: unknown element type id (buz::u[0] access).
806   D.addReloc({88, 6, D.addString("0:0:0"), BTF::FIELD_BYTE_OFFSET});
807   // Incorrect relocation: unknown member type id (buz::v access).
808   D.addReloc({96, 6, D.addString("0:1:0"), BTF::FIELD_BYTE_OFFSET});
809   // Incorrect relocation: non structural type in the middle of access string
810   //   struct bar::v.<something>.
811   D.addReloc({104, 4, D.addString("0:1:0"), BTF::FIELD_BYTE_OFFSET});
812 
813   BTFParser BTF;
814   Error E = BTF.parse(D.makeObj());
815   EXPECT_FALSE(E);
816 
817   SYMBOLIZE(SA({0, 1}), "<byte_off> [4] struct bar::v (0:1)");
818   SYMBOLIZE(SA({8, 1}), "<byte_sz> [4] struct bar::v (0:1)");
819   SYMBOLIZE(SA({16, 1}), "<field_exists> [4] struct bar::v (0:1)");
820   SYMBOLIZE(SA({24, 1}), "<signed> [4] struct bar::v (0:1)");
821   SYMBOLIZE(SA({32, 1}), "<lshift_u64> [4] struct bar::v (0:1)");
822   SYMBOLIZE(SA({40, 1}), "<rshift_u64> [4] struct bar::v (0:1)");
823   SYMBOLIZE(SA({48, 1}), "<byte_off> [4] struct bar::[7].v (7:1)");
824   SYMBOLIZE(SA({56, 1}), "<byte_off> [4] struct bar::u[1].a (0:0:1:0)");
825   SYMBOLIZE(SA({64, 1}), "<byte_off> [4] struct bar::u[1].b (0:0:1:1)");
826   SYMBOLIZE(SA({72, 1}), "<byte_off> [4] '' <field spec too short>");
827   SYMBOLIZE(SA({80, 1}),
828             "<byte_off> [4] '0:2' "
829             "<member index 2 for spec sub-string 1 is out of range>");
830   SYMBOLIZE(SA({88, 1}), "<byte_off> [6] '0:0:0' "
831                          "<unknown element type id 42 for spec sub-string 2>");
832   SYMBOLIZE(SA({96, 1}), "<byte_off> [6] '0:1:0' "
833                          "<unknown member type id 42 for spec sub-string 1>");
834   SYMBOLIZE(SA({104, 1}), "<byte_off> [4] '0:1:0' "
835                           "<unexpected type kind 1 for spec sub-string 2>");
836 }
837 
TEST(BTFParserTest,fieldRelocsMods)838 TEST(BTFParserTest, fieldRelocsMods) {
839   MockData2 D;
840   // struct foo {
841   //   int u;
842   // }
843   // typedef struct foo bar;
844   // struct buz {
845   //   const bar v;
846   // }
847   // typedef buz quux;
848   // const volatile restrict quux <some-var>;
849   uint32_t Int =
850       D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});
851   D.addTail((uint32_t)0);
852   uint32_t Foo =
853       D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});
854   D.addTail(BTF::BTFMember({D.addString("u"), Int, 0}));
855   uint32_t Bar =
856       D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_TYPEDEF), {Foo}});
857   uint32_t CBar =
858       D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_CONST), {Bar}});
859   uint32_t Buz =
860       D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});
861   D.addTail(BTF::BTFMember({D.addString("v"), CBar, 0}));
862   uint32_t Quux =
863       D.addType({D.addString("quux"), mkInfo(BTF::BTF_KIND_TYPEDEF), {Buz}});
864   uint32_t RQuux =
865       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_RESTRICT), {Quux}});
866   uint32_t VRQuux =
867       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_VOLATILE), {RQuux}});
868   uint32_t CVRQuux =
869       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {VRQuux}});
870   uint32_t CUnknown =
871       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {77}});
872   uint32_t CVUnknown =
873       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_VOLATILE), {CUnknown}});
874 
875   D.addRelocSec({D.addString("foo"), 0});
876   D.addReloc({0, Bar, D.addString("0:0"), BTF::FIELD_BYTE_OFFSET});
877   D.addReloc({8, CVRQuux, D.addString("0:0:0"), BTF::FIELD_BYTE_OFFSET});
878   D.addReloc({16, CVUnknown, D.addString("0:1:2"), BTF::FIELD_BYTE_OFFSET});
879 
880   BTFParser BTF;
881   Error E = BTF.parse(D.makeObj());
882   EXPECT_FALSE(E);
883 
884   // Should show modifiers / name of typedef.
885   SYMBOLIZE(SA({0, 1}), "<byte_off> [3] typedef bar::u (0:0)");
886   SYMBOLIZE(SA({8, 1}),
887             "<byte_off> [9] const volatile restrict typedef quux::v.u (0:0:0)");
888   SYMBOLIZE(SA({16, 1}),
889             "<byte_off> [11] '0:1:2' <unknown type id: 77 in modifiers chain>");
890 }
891 
TEST(BTFParserTest,relocTypeTagAndVoid)892 TEST(BTFParserTest, relocTypeTagAndVoid) {
893   MockData2 D;
894   // __attribute__((type_tag("tag"))) void
895   uint32_t Tag =
896       D.addType({D.addString("tag"), mkInfo(BTF::BTF_KIND_TYPE_TAG), {0}});
897 
898   D.addRelocSec({D.addString("foo"), 0});
899   D.addReloc({0, Tag, D.addString("0"), BTF::TYPE_EXISTENCE});
900   D.addReloc({8, 0 /* void */, D.addString("0"), BTF::TYPE_EXISTENCE});
901 
902   BTFParser BTF;
903   Error E = BTF.parse(D.makeObj());
904   EXPECT_FALSE(E);
905 
906   SYMBOLIZE(SA({0, 1}), "<type_exists> [1] type_tag(\"tag\") void");
907   SYMBOLIZE(SA({8, 1}), "<type_exists> [0] void");
908 }
909 
TEST(BTFParserTest,longRelocModifiersCycle)910 TEST(BTFParserTest, longRelocModifiersCycle) {
911   MockData2 D;
912 
913   D.addType(
914       {D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {1 /* ourselves */}});
915   D.addRelocSec({D.addString("foo"), 0});
916   D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});
917 
918   BTFParser BTF;
919   Error E = BTF.parse(D.makeObj());
920   EXPECT_FALSE(E);
921 
922   SYMBOLIZE(SA({0, 1}), "<type_exists> [1] '' <modifiers chain is too long>");
923 }
924 
TEST(BTFParserTest,relocAnonFieldsAndTypes)925 TEST(BTFParserTest, relocAnonFieldsAndTypes) {
926   MockData2 D;
927 
928   // struct {
929   //   int :32;
930   // } v;
931   uint32_t Int =
932       D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});
933   D.addTail((uint32_t)0);
934   uint32_t Anon =
935       D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});
936   D.addTail(BTF::BTFMember({D.addString(""), Int, 0}));
937 
938   D.addRelocSec({D.addString("foo"), 0});
939   D.addReloc({0, Anon, D.addString("0"), BTF::TYPE_EXISTENCE});
940   D.addReloc({8, Anon, D.addString("0:0"), BTF::FIELD_BYTE_OFFSET});
941 
942   BTFParser BTF;
943   Error E = BTF.parse(D.makeObj());
944   EXPECT_FALSE(E);
945 
946   SYMBOLIZE(SA({0, 1}), "<type_exists> [2] struct <anon 2>");
947   SYMBOLIZE(SA({8, 1}), "<byte_off> [2] struct <anon 2>::<anon 0> (0:0)");
948 }
949 
TEST(BTFParserTest,miscBadRelos)950 TEST(BTFParserTest, miscBadRelos) {
951   MockData2 D;
952 
953   uint32_t S = D.addType({D.addString("S"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
954 
955   D.addRelocSec({D.addString("foo"), 0});
956   D.addReloc({0, 0, D.addString(""), 777});
957   D.addReloc({8, S, D.addString("abc"), BTF::FIELD_BYTE_OFFSET});
958   D.addReloc({16, S, D.addString("0#"), BTF::FIELD_BYTE_OFFSET});
959 
960   BTFParser BTF;
961   Error E = BTF.parse(D.makeObj());
962   EXPECT_FALSE(E);
963 
964   SYMBOLIZE(SA({0, 1}),
965             "<reloc kind #777> [0] '' <unknown relocation kind: 777>");
966   SYMBOLIZE(SA({8, 1}), "<byte_off> [1] 'abc' <spec string is not a number>");
967   SYMBOLIZE(SA({16, 1}),
968             "<byte_off> [1] '0#' <unexpected spec string delimiter: '#'>");
969 }
970 
TEST(BTFParserTest,relocsMultipleSections)971 TEST(BTFParserTest, relocsMultipleSections) {
972   MockData2 D;
973 
974   uint32_t S = D.addType({D.addString("S"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
975   uint32_t T = D.addType({D.addString("T"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
976 
977   D.addRelocSec({D.addString("foo"), 0});
978   D.addReloc({0, S, D.addString(""), BTF::TYPE_EXISTENCE});
979   D.addReloc({8, S, D.addString(""), BTF::TYPE_EXISTENCE});
980 
981   D.addRelocSec({D.addString("bar"), 0});
982   D.addReloc({8, T, D.addString(""), BTF::TYPE_EXISTENCE});
983   D.addReloc({16, T, D.addString(""), BTF::TYPE_EXISTENCE});
984 
985   BTFParser BTF;
986   Error E = BTF.parse(D.makeObj());
987   EXPECT_FALSE(E);
988 
989   EXPECT_TRUE(BTF.findFieldReloc({0, 1}));
990   EXPECT_TRUE(BTF.findFieldReloc({8, 1}));
991   EXPECT_FALSE(BTF.findFieldReloc({16, 1}));
992 
993   EXPECT_FALSE(BTF.findFieldReloc({0, 2}));
994   EXPECT_TRUE(BTF.findFieldReloc({8, 2}));
995   EXPECT_TRUE(BTF.findFieldReloc({16, 2}));
996 
997   EXPECT_FALSE(BTF.findFieldReloc({0, 3}));
998   EXPECT_FALSE(BTF.findFieldReloc({8, 3}));
999   EXPECT_FALSE(BTF.findFieldReloc({16, 3}));
1000 
1001   auto AssertReloType = [&](const SectionedAddress &A, const char *Name) {
1002     const BTF::BPFFieldReloc *Relo = BTF.findFieldReloc(A);
1003     ASSERT_TRUE(Relo);
1004     const BTF::CommonType *Type = BTF.findType(Relo->TypeID);
1005     ASSERT_TRUE(Type);
1006     EXPECT_EQ(BTF.findString(Type->NameOff), Name);
1007   };
1008 
1009   AssertReloType({8, 1}, "S");
1010   AssertReloType({8, 2}, "T");
1011 }
1012 
TEST(BTFParserTest,parserResetReloAndTypes)1013 TEST(BTFParserTest, parserResetReloAndTypes) {
1014   BTFParser BTF;
1015   MockData2 D;
1016 
1017   // First time: two types, two relocations.
1018   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
1019   D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
1020   D.addRelocSec({D.addString("foo"), 0});
1021   D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});
1022   D.addReloc({8, 2, D.addString(""), BTF::TYPE_EXISTENCE});
1023 
1024   Error E1 = BTF.parse(D.makeObj());
1025   EXPECT_FALSE(E1);
1026 
1027   ASSERT_TRUE(BTF.findType(1));
1028   EXPECT_EQ(BTF.findString(BTF.findType(1)->NameOff), "foo");
1029   EXPECT_TRUE(BTF.findType(2));
1030   EXPECT_TRUE(BTF.findFieldReloc({0, 1}));
1031   EXPECT_TRUE(BTF.findFieldReloc({8, 1}));
1032 
1033   // Second time: one type, one relocation.
1034   D.reset();
1035   D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
1036   D.addRelocSec({D.addString("foo"), 0});
1037   D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});
1038 
1039   Error E2 = BTF.parse(D.makeObj());
1040   EXPECT_FALSE(E2);
1041 
1042   ASSERT_TRUE(BTF.findType(1));
1043   EXPECT_EQ(BTF.findString(BTF.findType(1)->NameOff), "buz");
1044   EXPECT_FALSE(BTF.findType(2));
1045   EXPECT_TRUE(BTF.findFieldReloc({0, 1}));
1046   EXPECT_FALSE(BTF.findFieldReloc({8, 1}));
1047 }
1048 
TEST(BTFParserTest,selectiveLoad)1049 TEST(BTFParserTest, selectiveLoad) {
1050   BTFParser BTF1, BTF2, BTF3;
1051   MockData2 D;
1052 
1053   D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});
1054   D.addRelocSec({D.addString("foo"), 0});
1055   D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});
1056   D.addLinesSec({D.addString("foo"), 0});
1057   D.addLine({0, D.addString("file.c"), D.addString("some line"), LC(2, 3)});
1058 
1059   BTFParser::ParseOptions Opts;
1060 
1061   ObjectFile &Obj1 = D.makeObj();
1062   Opts = {};
1063   Opts.LoadLines = true;
1064   ASSERT_SUCCEEDED(BTF1.parse(Obj1, Opts));
1065 
1066   Opts = {};
1067   Opts.LoadTypes = true;
1068   ASSERT_SUCCEEDED(BTF2.parse(Obj1, Opts));
1069 
1070   Opts = {};
1071   Opts.LoadRelocs = true;
1072   ASSERT_SUCCEEDED(BTF3.parse(Obj1, Opts));
1073 
1074   EXPECT_TRUE(BTF1.findLineInfo({0, 1}));
1075   EXPECT_FALSE(BTF2.findLineInfo({0, 1}));
1076   EXPECT_FALSE(BTF3.findLineInfo({0, 1}));
1077 
1078   EXPECT_FALSE(BTF1.findType(1));
1079   EXPECT_TRUE(BTF2.findType(1));
1080   EXPECT_FALSE(BTF3.findType(1));
1081 
1082   EXPECT_FALSE(BTF1.findFieldReloc({0, 1}));
1083   EXPECT_FALSE(BTF2.findFieldReloc({0, 1}));
1084   EXPECT_TRUE(BTF3.findFieldReloc({0, 1}));
1085 }
1086 
1087 } // namespace
1088