1086 lines · cpp
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-exception6//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 15using namespace llvm;16using namespace llvm::object;17 18#define LC(Line, Col) ((Line << 10u) | Col)19#define ASSERT_SUCCEEDED(E) ASSERT_THAT_ERROR((E), Succeeded())20 21const char BTFEndOfData[] =22 "error while reading .BTF section: unexpected end of data";23const char BTFExtEndOfData[] =24 "error while reading .BTF.ext section: unexpected end of data";25 26static raw_ostream &operator<<(raw_ostream &OS, const yaml::BinaryRef &Ref) {27 Ref.writeAsHex(OS);28 return OS;29}30 31template <typename T>32static 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 36namespace {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 of39// 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 values45// valid for a small example with a few sections, fields could be46// modified before a call to `makeObj()` to test parser with invalid47// input, etc.48 49struct MockData1 {50// Use "pragma pack" to model .BTF & .BTF.ext sections content using51// '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 67 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 96 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 112 ObjectFile &makeObj() {113 std::string Buffer;114 raw_string_ostream Yaml(Buffer);115 Yaml << R"(116!ELF117FileHeader:118 Class: ELFCLASS64)";119 if (sys::IsBigEndianHost)120 Yaml << "\n Data: ELFDATA2MSB";121 else122 Yaml << "\n Data: ELFDATA2LSB";123 Yaml << R"(124 Type: ET_REL125 Machine: EM_BPF126Sections:127 - Name: foo128 Type: SHT_PROGBITS129 Size: 0x0130 - Name: bar131 Type: SHT_PROGBITS132 Size: 0x0)";133 134 if (BTFSectionLen >= 0)135 Yaml << R"(136 - Name: .BTF137 Type: SHT_PROGBITS138 Content: )"139 << makeBinRef(&BTF, BTFSectionLen);140 141 if (ExtSectionLen >= 0)142 Yaml << R"(143 - Name: .BTF.ext144 Type: SHT_PROGBITS145 Content: )"146 << makeBinRef(&Ext, ExtSectionLen);147 148 Obj = yaml::yaml2ObjectFile(Storage, Buffer,149 [](const Twine &Err) { errs() << Err; });150 return *Obj;151 }152};153 154TEST(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 198TEST(BTFParserTest, badSectionNameOffset) {199 BTFParser BTF;200 MockData1 Mock;201 // "foo" is section #1, corrupting it's name offset will make impossible202 // 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 220TEST(BTFParserTest, badBTFMagic) {221 MockData1 Mock;222 Mock.BTF.Header.Magic = 42;223 EXPECT_PARSE_ERROR(Mock, "invalid .BTF magic: 2a");224}225 226TEST(BTFParserTest, badBTFVersion) {227 MockData1 Mock;228 Mock.BTF.Header.Version = 42;229 EXPECT_PARSE_ERROR(Mock, "unsupported .BTF version: 42");230}231 232TEST(BTFParserTest, badBTFHdrLen) {233 MockData1 Mock;234 Mock.BTF.Header.HdrLen = 5;235 EXPECT_PARSE_ERROR(Mock, "unexpected .BTF header length: 5");236}237 238TEST(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 251TEST(BTFParserTest, badBTFExtMagic) {252 MockData1 Mock;253 Mock.Ext.Header.Magic = 42;254 EXPECT_PARSE_ERROR(Mock, "invalid .BTF.ext magic: 2a");255}256 257TEST(BTFParserTest, badBTFExtVersion) {258 MockData1 Mock;259 Mock.Ext.Header.Version = 42;260 EXPECT_PARSE_ERROR(Mock, "unsupported .BTF.ext version: 42");261}262 263TEST(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 273TEST(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 289TEST(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 299TEST(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 307TEST(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() is322// called several times.323TEST(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 making332 // 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 341TEST(BTFParserTest, btfContext) {342 MockData1 Mock;343 BTFParser BTF;344 std::unique_ptr<BTFContext> Ctx = BTFContext::create(Mock.makeObj());345 346 std::optional<DILineInfo> I1 = Ctx->getLineInfoForAddress({16, 1});347 EXPECT_TRUE(I1.has_value());348 EXPECT_EQ(I1->Line, 7u);349 EXPECT_EQ(I1->Column, 1u);350 EXPECT_EQ(I1->FileName, "a.c");351 EXPECT_EQ(I1->LineSource, "first line");352 353 std::optional<DILineInfo> I2 = Ctx->getLineInfoForAddress({24, 1});354 EXPECT_FALSE(I2.has_value());355}356 357static uint32_t mkInfo(uint32_t Kind) { return Kind << 24; }358 359template <typename T> static void append(std::string &S, const T &What) {360 S.append((const char *)&What, sizeof(What));361}362 363class MockData2 {364 SmallString<0> ObjStorage;365 std::unique_ptr<ObjectFile> Obj;366 std::string Types;367 std::string Strings;368 std::string Relocs;369 std::string Lines;370 unsigned TotalTypes;371 int LastRelocSecIdx;372 unsigned NumRelocs;373 int LastLineSecIdx;374 unsigned NumLines;375 376public:377 MockData2() { reset(); }378 379 unsigned totalTypes() const { return TotalTypes; }380 381 uint32_t addString(StringRef S) {382 uint32_t Off = Strings.size();383 Strings.append(S.data(), S.size());384 Strings.append("\0", 1);385 return Off;386 };387 388 uint32_t addType(const BTF::CommonType &Tp) {389 append(Types, Tp);390 return ++TotalTypes;391 }392 393 template <typename T> void addTail(const T &Tp) { append(Types, Tp); }394 395 void resetTypes() {396 Types.resize(0);397 TotalTypes = 0;398 }399 400 void reset() {401 ObjStorage.clear();402 Types.resize(0);403 Strings.resize(0);404 Relocs.resize(0);405 Lines.resize(0);406 TotalTypes = 0;407 LastRelocSecIdx = -1;408 NumRelocs = 0;409 LastLineSecIdx = -1;410 NumLines = 0;411 }412 413 void finishRelocSec() {414 if (LastRelocSecIdx == -1)415 return;416 417 BTF::SecFieldReloc *SecInfo =418 (BTF::SecFieldReloc *)&Relocs[LastRelocSecIdx];419 SecInfo->NumFieldReloc = NumRelocs;420 LastRelocSecIdx = -1;421 NumRelocs = 0;422 }423 424 void finishLineSec() {425 if (LastLineSecIdx == -1)426 return;427 428 BTF::SecLineInfo *SecInfo = (BTF::SecLineInfo *)&Lines[LastLineSecIdx];429 SecInfo->NumLineInfo = NumLines;430 NumLines = 0;431 LastLineSecIdx = -1;432 }433 434 void addRelocSec(const BTF::SecFieldReloc &R) {435 finishRelocSec();436 LastRelocSecIdx = Relocs.size();437 append(Relocs, R);438 }439 440 void addReloc(const BTF::BPFFieldReloc &R) {441 append(Relocs, R);442 ++NumRelocs;443 }444 445 void addLinesSec(const BTF::SecLineInfo &R) {446 finishLineSec();447 LastLineSecIdx = Lines.size();448 append(Lines, R);449 }450 451 void addLine(const BTF::BPFLineInfo &R) {452 append(Lines, R);453 ++NumLines;454 }455 456 ObjectFile &makeObj() {457 finishRelocSec();458 finishLineSec();459 460 BTF::Header BTFHeader = {};461 BTFHeader.Magic = BTF::MAGIC;462 BTFHeader.Version = 1;463 BTFHeader.HdrLen = sizeof(BTFHeader);464 BTFHeader.StrOff = 0;465 BTFHeader.StrLen = Strings.size();466 BTFHeader.TypeOff = Strings.size();467 BTFHeader.TypeLen = Types.size();468 469 std::string BTFSec;470 append(BTFSec, BTFHeader);471 BTFSec.append(Strings);472 BTFSec.append(Types);473 474 BTF::ExtHeader ExtHeader = {};475 ExtHeader.Magic = BTF::MAGIC;476 ExtHeader.Version = 1;477 ExtHeader.HdrLen = sizeof(ExtHeader);478 ExtHeader.FieldRelocOff = 0;479 ExtHeader.FieldRelocLen = Relocs.size() + sizeof(uint32_t);480 ExtHeader.LineInfoOff = ExtHeader.FieldRelocLen;481 ExtHeader.LineInfoLen = Lines.size() + sizeof(uint32_t);482 483 std::string ExtSec;484 append(ExtSec, ExtHeader);485 append(ExtSec, (uint32_t)sizeof(BTF::BPFFieldReloc));486 ExtSec.append(Relocs);487 append(ExtSec, (uint32_t)sizeof(BTF::BPFLineInfo));488 ExtSec.append(Lines);489 490 std::string YamlBuffer;491 raw_string_ostream Yaml(YamlBuffer);492 Yaml << R"(493!ELF494FileHeader:495 Class: ELFCLASS64)";496 if (sys::IsBigEndianHost)497 Yaml << "\n Data: ELFDATA2MSB";498 else499 Yaml << "\n Data: ELFDATA2LSB";500 Yaml << R"(501 Type: ET_REL502 Machine: EM_BPF503Sections:504 - Name: foo505 Type: SHT_PROGBITS506 Size: 0x80507 - Name: bar508 Type: SHT_PROGBITS509 Size: 0x80510 - Name: .BTF511 Type: SHT_PROGBITS512 Content: )"513 << makeBinRef(BTFSec.data(), BTFSec.size());514 Yaml << R"(515 - Name: .BTF.ext516 Type: SHT_PROGBITS517 Content: )"518 << makeBinRef(ExtSec.data(), ExtSec.size());519 520 Obj = yaml::yaml2ObjectFile(ObjStorage, YamlBuffer,521 [](const Twine &Err) { errs() << Err; });522 return *Obj;523 }524};525 526TEST(BTFParserTest, allTypeKinds) {527 MockData2 D;528 D.addType({D.addString("1"), mkInfo(BTF::BTF_KIND_INT), {4}});529 D.addTail((uint32_t)0);530 D.addType({D.addString("2"), mkInfo(BTF::BTF_KIND_PTR), {1}});531 D.addType({D.addString("3"), mkInfo(BTF::BTF_KIND_ARRAY), {0}});532 D.addTail(BTF::BTFArray({1, 1, 2}));533 D.addType({D.addString("4"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});534 D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));535 D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));536 D.addType({D.addString("5"), mkInfo(BTF::BTF_KIND_UNION) | 3, {8}});537 D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));538 D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));539 D.addTail(BTF::BTFMember({D.addString("c"), 1, 0}));540 D.addType({D.addString("6"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});541 D.addTail(BTF::BTFEnum({D.addString("U"), 1}));542 D.addTail(BTF::BTFEnum({D.addString("V"), 2}));543 D.addType({D.addString("7"), mkInfo(BTF::BTF_KIND_ENUM64) | 1, {4}});544 D.addTail(BTF::BTFEnum64({D.addString("W"), 0, 1}));545 D.addType(546 {D.addString("8"), BTF::FWD_UNION_FLAG | mkInfo(BTF::BTF_KIND_FWD), {0}});547 D.addType({D.addString("9"), mkInfo(BTF::BTF_KIND_TYPEDEF), {1}});548 D.addType({D.addString("10"), mkInfo(BTF::BTF_KIND_VOLATILE), {1}});549 D.addType({D.addString("11"), mkInfo(BTF::BTF_KIND_CONST), {1}});550 D.addType({D.addString("12"), mkInfo(BTF::BTF_KIND_RESTRICT), {1}});551 D.addType({D.addString("13"), mkInfo(BTF::BTF_KIND_FUNC_PROTO) | 1, {1}});552 D.addTail(BTF::BTFParam({D.addString("P"), 2}));553 D.addType({D.addString("14"), mkInfo(BTF::BTF_KIND_FUNC), {13}});554 D.addType({D.addString("15"), mkInfo(BTF::BTF_KIND_VAR), {2}});555 D.addTail((uint32_t)0);556 D.addType({D.addString("16"), mkInfo(BTF::BTF_KIND_DATASEC) | 3, {0}});557 D.addTail(BTF::BTFDataSec({1, 0, 4}));558 D.addTail(BTF::BTFDataSec({1, 4, 4}));559 D.addTail(BTF::BTFDataSec({1, 8, 4}));560 D.addType({D.addString("17"), mkInfo(BTF::BTF_KIND_FLOAT), {4}});561 D.addType({D.addString("18"), mkInfo(BTF::BTF_KIND_DECL_TAG), {0}});562 D.addTail((uint32_t)-1);563 D.addType({D.addString("19"), mkInfo(BTF::BTF_KIND_TYPE_TAG), {0}});564 565 BTFParser BTF;566 Error Err = BTF.parse(D.makeObj());567 EXPECT_FALSE(Err);568 569 EXPECT_EQ(D.totalTypes() + 1 /* +1 for void */, BTF.typesCount());570 for (unsigned Id = 1; Id < D.totalTypes() + 1; ++Id) {571 const BTF::CommonType *Tp = BTF.findType(Id);572 ASSERT_TRUE(Tp);573 std::string IdBuf;574 raw_string_ostream IdBufStream(IdBuf);575 IdBufStream << Id;576 EXPECT_EQ(BTF.findString(Tp->NameOff), IdBuf);577 }578}579 580TEST(BTFParserTest, bigStruct) {581 const uint32_t N = 1000u;582 MockData2 D;583 uint32_t FStr = D.addString("f");584 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_INT), {4}});585 D.addTail((uint32_t)0);586 D.addType({D.addString("big"), mkInfo(BTF::BTF_KIND_STRUCT) | N, {8}});587 for (unsigned I = 0; I < N; ++I)588 D.addTail(BTF::BTFMember({FStr, 1, 0}));589 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_INT), {4}});590 D.addTail((uint32_t)0);591 592 BTFParser BTF;593 ASSERT_SUCCEEDED(BTF.parse(D.makeObj()));594 ASSERT_EQ(BTF.typesCount(), 4u /* +1 for void */);595 const BTF::CommonType *Foo = BTF.findType(1);596 const BTF::CommonType *Big = BTF.findType(2);597 const BTF::CommonType *Bar = BTF.findType(3);598 ASSERT_TRUE(Foo);599 ASSERT_TRUE(Big);600 ASSERT_TRUE(Bar);601 EXPECT_EQ(BTF.findString(Foo->NameOff), "foo");602 EXPECT_EQ(BTF.findString(Big->NameOff), "big");603 EXPECT_EQ(BTF.findString(Bar->NameOff), "bar");604 EXPECT_EQ(Big->getVlen(), N);605}606 607TEST(BTFParserTest, incompleteTypes) {608 MockData2 D;609 auto IncompleteType = [&](const BTF::CommonType &Tp) {610 D.resetTypes();611 D.addType(Tp);612 EXPECT_PARSE_ERROR(D, "incomplete type definition in .BTF section");613 };614 615 // All kinds that need tail.616 IncompleteType({D.addString("a"), mkInfo(BTF::BTF_KIND_INT), {4}});617 IncompleteType({D.addString("b"), mkInfo(BTF::BTF_KIND_ARRAY), {0}});618 IncompleteType({D.addString("c"), mkInfo(BTF::BTF_KIND_VAR), {0}});619 IncompleteType({D.addString("d"), mkInfo(BTF::BTF_KIND_DECL_TAG), {0}});620 621 // All kinds with vlen.622 IncompleteType({D.addString("a"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});623 IncompleteType({D.addString("b"), mkInfo(BTF::BTF_KIND_UNION) | 3, {8}});624 IncompleteType({D.addString("c"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});625 IncompleteType({D.addString("d"), mkInfo(BTF::BTF_KIND_ENUM64) | 1, {4}});626 IncompleteType({D.addString("e"), mkInfo(BTF::BTF_KIND_FUNC_PROTO) | 1, {1}});627 IncompleteType({D.addString("f"), mkInfo(BTF::BTF_KIND_DATASEC) | 3, {0}});628 629 // An unexpected tail.630 D.resetTypes();631 D.addTail((uint32_t)0);632 EXPECT_PARSE_ERROR(D, "incomplete type definition in .BTF section");633}634 635// Use macro to preserve line number in error message.636#define SYMBOLIZE(SecAddr, Expected) \637 do { \638 const BTF::BPFFieldReloc *R = BTF.findFieldReloc((SecAddr)); \639 ASSERT_TRUE(R); \640 SmallString<64> Symbolized; \641 BTF.symbolize(R, Symbolized); \642 EXPECT_EQ(Symbolized, (Expected)); \643 } while (false)644 645// Shorter name for initializers below.646using SA = SectionedAddress;647 648TEST(BTFParserTest, typeRelocs) {649 MockData2 D;650 uint32_t Zero = D.addString("0");651 // id 1: struct foo {}652 // id 2: union bar;653 // id 3: struct buz;654 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});655 D.addType({D.addString("bar"),656 mkInfo(BTF::BTF_KIND_FWD) | BTF::FWD_UNION_FLAG,657 {0}});658 D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_FWD), {0}});659 D.addRelocSec({D.addString("foo"), 7});660 // List of all possible correct type relocations for type id #1.661 D.addReloc({0, 1, Zero, BTF::BTF_TYPE_ID_LOCAL});662 D.addReloc({8, 1, Zero, BTF::BTF_TYPE_ID_REMOTE});663 D.addReloc({16, 1, Zero, BTF::TYPE_EXISTENCE});664 D.addReloc({24, 1, Zero, BTF::TYPE_MATCH});665 D.addReloc({32, 1, Zero, BTF::TYPE_SIZE});666 // Forward declarations.667 D.addReloc({40, 2, Zero, BTF::TYPE_SIZE});668 D.addReloc({48, 3, Zero, BTF::TYPE_SIZE});669 // Incorrect type relocation: bad type id.670 D.addReloc({56, 42, Zero, BTF::TYPE_SIZE});671 // Incorrect type relocation: spec should be '0'.672 D.addReloc({64, 1, D.addString("10"), BTF::TYPE_SIZE});673 674 BTFParser BTF;675 Error E = BTF.parse(D.makeObj());676 EXPECT_FALSE(E);677 678 SYMBOLIZE(SA({0, 1}), "<local_type_id> [1] struct foo");679 SYMBOLIZE(SA({8, 1}), "<target_type_id> [1] struct foo");680 SYMBOLIZE(SA({16, 1}), "<type_exists> [1] struct foo");681 SYMBOLIZE(SA({24, 1}), "<type_matches> [1] struct foo");682 SYMBOLIZE(SA({32, 1}), "<type_size> [1] struct foo");683 SYMBOLIZE(SA({40, 1}), "<type_size> [2] fwd union bar");684 SYMBOLIZE(SA({48, 1}), "<type_size> [3] fwd struct buz");685 SYMBOLIZE(SA({56, 1}), "<type_size> [42] '0' <unknown type id: 42>");686 SYMBOLIZE(SA({64, 1}),687 "<type_size> [1] '10' "688 "<unexpected type-based relocation spec: should be '0'>");689}690 691TEST(BTFParserTest, enumRelocs) {692 MockData2 D;693 // id 1: enum { U, V }694 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});695 D.addTail(BTF::BTFEnum({D.addString("U"), 1}));696 D.addTail(BTF::BTFEnum({D.addString("V"), 2}));697 // id 2: int698 D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});699 D.addTail((uint32_t)0);700 // id 3: enum: uint64_t { A, B }701 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_ENUM64) | 2, {8}});702 D.addTail(BTF::BTFEnum64({D.addString("A"), 1, 0}));703 D.addTail(BTF::BTFEnum64({D.addString("B"), 2, 0}));704 705 D.addRelocSec({D.addString("foo"), 5});706 // An ok relocation accessing value #1: U.707 D.addReloc({0, 1, D.addString("0"), BTF::ENUM_VALUE_EXISTENCE});708 // An ok relocation accessing value #2: V.709 D.addReloc({8, 1, D.addString("1"), BTF::ENUM_VALUE});710 // Incorrect relocation: too many elements in string "1:0".711 D.addReloc({16, 1, D.addString("1:0"), BTF::ENUM_VALUE});712 // Incorrect relocation: type id "2" is not an enum.713 D.addReloc({24, 2, D.addString("1"), BTF::ENUM_VALUE});714 // Incorrect relocation: value #42 does not exist for enum "foo".715 D.addReloc({32, 1, D.addString("42"), BTF::ENUM_VALUE});716 // An ok relocation accessing value #1: A.717 D.addReloc({40, 3, D.addString("0"), BTF::ENUM_VALUE_EXISTENCE});718 // An ok relocation accessing value #2: B.719 D.addReloc({48, 3, D.addString("1"), BTF::ENUM_VALUE});720 721 BTFParser BTF;722 Error E = BTF.parse(D.makeObj());723 EXPECT_FALSE(E);724 725 SYMBOLIZE(SA({0, 1}), "<enumval_exists> [1] enum foo::U = 1");726 SYMBOLIZE(SA({8, 1}), "<enumval_value> [1] enum foo::V = 2");727 SYMBOLIZE(728 SA({16, 1}),729 "<enumval_value> [1] '1:0' <unexpected enumval relocation spec size>");730 SYMBOLIZE(731 SA({24, 1}),732 "<enumval_value> [2] '1' <unexpected type kind for enum relocation: 1>");733 SYMBOLIZE(SA({32, 1}), "<enumval_value> [1] '42' <bad value index: 42>");734 SYMBOLIZE(SA({40, 1}), "<enumval_exists> [3] enum bar::A = 1");735 SYMBOLIZE(SA({48, 1}), "<enumval_value> [3] enum bar::B = 2");736}737 738TEST(BTFParserTest, enumRelocsMods) {739 MockData2 D;740 // id 1: enum { U, V }741 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_ENUM) | 2, {4}});742 D.addTail(BTF::BTFEnum({D.addString("U"), 1}));743 D.addTail(BTF::BTFEnum({D.addString("V"), 2}));744 // id 2: typedef enum foo a;745 D.addType({D.addString("a"), mkInfo(BTF::BTF_KIND_TYPEDEF), {1}});746 // id 3: const enum foo;747 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {1}});748 749 D.addRelocSec({D.addString("foo"), 0});750 D.addReloc({0, 2, D.addString("0"), BTF::ENUM_VALUE});751 D.addReloc({8, 3, D.addString("1"), BTF::ENUM_VALUE});752 753 BTFParser BTF;754 Error E = BTF.parse(D.makeObj());755 EXPECT_FALSE(E);756 757 SYMBOLIZE(SA({0, 1}), "<enumval_value> [2] typedef a::U = 1");758 SYMBOLIZE(SA({8, 1}), "<enumval_value> [3] const enum foo::V = 2");759}760 761TEST(BTFParserTest, fieldRelocs) {762 MockData2 D;763 // id 1: int764 D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});765 D.addTail((uint32_t)0);766 // id 2: struct foo { int a; int b; }767 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});768 D.addTail(BTF::BTFMember({D.addString("a"), 1, 0}));769 D.addTail(BTF::BTFMember({D.addString("b"), 1, 0}));770 // id 3: array of struct foo.771 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_ARRAY), {0}});772 D.addTail(BTF::BTFArray({2, 1, 2}));773 // id 4: struct bar { struct foo u[2]; int v; }774 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});775 D.addTail(BTF::BTFMember({D.addString("u"), 3, 0}));776 D.addTail(BTF::BTFMember({D.addString("v"), 1, 0}));777 // id 5: array with bad element type id.778 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_ARRAY), {0}});779 D.addTail(BTF::BTFArray({42, 1, 2}));780 // id 6: struct buz { <bad type> u[2]; <bad type> v; }781 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT) | 2, {8}});782 D.addTail(BTF::BTFMember({D.addString("u"), 5, 0}));783 D.addTail(BTF::BTFMember({D.addString("v"), 42, 0}));784 785 D.addRelocSec({D.addString("foo"), 0 /* patched automatically */});786 // All field relocations kinds for struct bar::v.787 D.addReloc({0, 4, D.addString("0:1"), BTF::FIELD_BYTE_OFFSET});788 D.addReloc({8, 4, D.addString("0:1"), BTF::FIELD_BYTE_SIZE});789 D.addReloc({16, 4, D.addString("0:1"), BTF::FIELD_EXISTENCE});790 D.addReloc({24, 4, D.addString("0:1"), BTF::FIELD_SIGNEDNESS});791 D.addReloc({32, 4, D.addString("0:1"), BTF::FIELD_LSHIFT_U64});792 D.addReloc({40, 4, D.addString("0:1"), BTF::FIELD_RSHIFT_U64});793 // Non-zero first idx.794 D.addReloc({48, 4, D.addString("7:1"), BTF::FIELD_BYTE_OFFSET});795 // Access through array and struct: struct bar::u[1].a.796 D.addReloc({56, 4, D.addString("0:0:1:0"), BTF::FIELD_BYTE_OFFSET});797 // Access through array and struct: struct bar::u[1].b.798 D.addReloc({64, 4, D.addString("0:0:1:1"), BTF::FIELD_BYTE_OFFSET});799 // Incorrect relocation: empty access string.800 D.addReloc({72, 4, D.addString(""), BTF::FIELD_BYTE_OFFSET});801 // Incorrect relocation: member index out of range (only two members in bar).802 D.addReloc({80, 4, D.addString("0:2"), BTF::FIELD_BYTE_OFFSET});803 // Incorrect relocation: unknown element type id (buz::u[0] access).804 D.addReloc({88, 6, D.addString("0:0:0"), BTF::FIELD_BYTE_OFFSET});805 // Incorrect relocation: unknown member type id (buz::v access).806 D.addReloc({96, 6, D.addString("0:1:0"), BTF::FIELD_BYTE_OFFSET});807 // Incorrect relocation: non structural type in the middle of access string808 // struct bar::v.<something>.809 D.addReloc({104, 4, D.addString("0:1:0"), BTF::FIELD_BYTE_OFFSET});810 811 BTFParser BTF;812 Error E = BTF.parse(D.makeObj());813 EXPECT_FALSE(E);814 815 SYMBOLIZE(SA({0, 1}), "<byte_off> [4] struct bar::v (0:1)");816 SYMBOLIZE(SA({8, 1}), "<byte_sz> [4] struct bar::v (0:1)");817 SYMBOLIZE(SA({16, 1}), "<field_exists> [4] struct bar::v (0:1)");818 SYMBOLIZE(SA({24, 1}), "<signed> [4] struct bar::v (0:1)");819 SYMBOLIZE(SA({32, 1}), "<lshift_u64> [4] struct bar::v (0:1)");820 SYMBOLIZE(SA({40, 1}), "<rshift_u64> [4] struct bar::v (0:1)");821 SYMBOLIZE(SA({48, 1}), "<byte_off> [4] struct bar::[7].v (7:1)");822 SYMBOLIZE(SA({56, 1}), "<byte_off> [4] struct bar::u[1].a (0:0:1:0)");823 SYMBOLIZE(SA({64, 1}), "<byte_off> [4] struct bar::u[1].b (0:0:1:1)");824 SYMBOLIZE(SA({72, 1}), "<byte_off> [4] '' <field spec too short>");825 SYMBOLIZE(SA({80, 1}),826 "<byte_off> [4] '0:2' "827 "<member index 2 for spec sub-string 1 is out of range>");828 SYMBOLIZE(SA({88, 1}), "<byte_off> [6] '0:0:0' "829 "<unknown element type id 42 for spec sub-string 2>");830 SYMBOLIZE(SA({96, 1}), "<byte_off> [6] '0:1:0' "831 "<unknown member type id 42 for spec sub-string 1>");832 SYMBOLIZE(SA({104, 1}), "<byte_off> [4] '0:1:0' "833 "<unexpected type kind 1 for spec sub-string 2>");834}835 836TEST(BTFParserTest, fieldRelocsMods) {837 MockData2 D;838 // struct foo {839 // int u;840 // }841 // typedef struct foo bar;842 // struct buz {843 // const bar v;844 // }845 // typedef buz quux;846 // const volatile restrict quux <some-var>;847 uint32_t Int =848 D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});849 D.addTail((uint32_t)0);850 uint32_t Foo =851 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});852 D.addTail(BTF::BTFMember({D.addString("u"), Int, 0}));853 uint32_t Bar =854 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_TYPEDEF), {Foo}});855 uint32_t CBar =856 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_CONST), {Bar}});857 uint32_t Buz =858 D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});859 D.addTail(BTF::BTFMember({D.addString("v"), CBar, 0}));860 uint32_t Quux =861 D.addType({D.addString("quux"), mkInfo(BTF::BTF_KIND_TYPEDEF), {Buz}});862 uint32_t RQuux =863 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_RESTRICT), {Quux}});864 uint32_t VRQuux =865 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_VOLATILE), {RQuux}});866 uint32_t CVRQuux =867 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {VRQuux}});868 uint32_t CUnknown =869 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {77}});870 uint32_t CVUnknown =871 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_VOLATILE), {CUnknown}});872 873 D.addRelocSec({D.addString("foo"), 0});874 D.addReloc({0, Bar, D.addString("0:0"), BTF::FIELD_BYTE_OFFSET});875 D.addReloc({8, CVRQuux, D.addString("0:0:0"), BTF::FIELD_BYTE_OFFSET});876 D.addReloc({16, CVUnknown, D.addString("0:1:2"), BTF::FIELD_BYTE_OFFSET});877 878 BTFParser BTF;879 Error E = BTF.parse(D.makeObj());880 EXPECT_FALSE(E);881 882 // Should show modifiers / name of typedef.883 SYMBOLIZE(SA({0, 1}), "<byte_off> [3] typedef bar::u (0:0)");884 SYMBOLIZE(SA({8, 1}),885 "<byte_off> [9] const volatile restrict typedef quux::v.u (0:0:0)");886 SYMBOLIZE(SA({16, 1}),887 "<byte_off> [11] '0:1:2' <unknown type id: 77 in modifiers chain>");888}889 890TEST(BTFParserTest, relocTypeTagAndVoid) {891 MockData2 D;892 // __attribute__((type_tag("tag"))) void893 uint32_t Tag =894 D.addType({D.addString("tag"), mkInfo(BTF::BTF_KIND_TYPE_TAG), {0}});895 896 D.addRelocSec({D.addString("foo"), 0});897 D.addReloc({0, Tag, D.addString("0"), BTF::TYPE_EXISTENCE});898 D.addReloc({8, 0 /* void */, D.addString("0"), BTF::TYPE_EXISTENCE});899 900 BTFParser BTF;901 Error E = BTF.parse(D.makeObj());902 EXPECT_FALSE(E);903 904 SYMBOLIZE(SA({0, 1}), "<type_exists> [1] type_tag(\"tag\") void");905 SYMBOLIZE(SA({8, 1}), "<type_exists> [0] void");906}907 908TEST(BTFParserTest, longRelocModifiersCycle) {909 MockData2 D;910 911 D.addType(912 {D.addString(""), mkInfo(BTF::BTF_KIND_CONST), {1 /* ourselves */}});913 D.addRelocSec({D.addString("foo"), 0});914 D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});915 916 BTFParser BTF;917 Error E = BTF.parse(D.makeObj());918 EXPECT_FALSE(E);919 920 SYMBOLIZE(SA({0, 1}), "<type_exists> [1] '' <modifiers chain is too long>");921}922 923TEST(BTFParserTest, relocAnonFieldsAndTypes) {924 MockData2 D;925 926 // struct {927 // int :32;928 // } v;929 uint32_t Int =930 D.addType({D.addString("int"), mkInfo(BTF::BTF_KIND_INT), {4}});931 D.addTail((uint32_t)0);932 uint32_t Anon =933 D.addType({D.addString(""), mkInfo(BTF::BTF_KIND_STRUCT) | 1, {4}});934 D.addTail(BTF::BTFMember({D.addString(""), Int, 0}));935 936 D.addRelocSec({D.addString("foo"), 0});937 D.addReloc({0, Anon, D.addString("0"), BTF::TYPE_EXISTENCE});938 D.addReloc({8, Anon, D.addString("0:0"), BTF::FIELD_BYTE_OFFSET});939 940 BTFParser BTF;941 Error E = BTF.parse(D.makeObj());942 EXPECT_FALSE(E);943 944 SYMBOLIZE(SA({0, 1}), "<type_exists> [2] struct <anon 2>");945 SYMBOLIZE(SA({8, 1}), "<byte_off> [2] struct <anon 2>::<anon 0> (0:0)");946}947 948TEST(BTFParserTest, miscBadRelos) {949 MockData2 D;950 951 uint32_t S = D.addType({D.addString("S"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});952 953 D.addRelocSec({D.addString("foo"), 0});954 D.addReloc({0, 0, D.addString(""), 777});955 D.addReloc({8, S, D.addString("abc"), BTF::FIELD_BYTE_OFFSET});956 D.addReloc({16, S, D.addString("0#"), BTF::FIELD_BYTE_OFFSET});957 958 BTFParser BTF;959 Error E = BTF.parse(D.makeObj());960 EXPECT_FALSE(E);961 962 SYMBOLIZE(SA({0, 1}),963 "<reloc kind #777> [0] '' <unknown relocation kind: 777>");964 SYMBOLIZE(SA({8, 1}), "<byte_off> [1] 'abc' <spec string is not a number>");965 SYMBOLIZE(SA({16, 1}),966 "<byte_off> [1] '0#' <unexpected spec string delimiter: '#'>");967}968 969TEST(BTFParserTest, relocsMultipleSections) {970 MockData2 D;971 972 uint32_t S = D.addType({D.addString("S"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});973 uint32_t T = D.addType({D.addString("T"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});974 975 D.addRelocSec({D.addString("foo"), 0});976 D.addReloc({0, S, D.addString(""), BTF::TYPE_EXISTENCE});977 D.addReloc({8, S, D.addString(""), BTF::TYPE_EXISTENCE});978 979 D.addRelocSec({D.addString("bar"), 0});980 D.addReloc({8, T, D.addString(""), BTF::TYPE_EXISTENCE});981 D.addReloc({16, T, D.addString(""), BTF::TYPE_EXISTENCE});982 983 BTFParser BTF;984 Error E = BTF.parse(D.makeObj());985 EXPECT_FALSE(E);986 987 EXPECT_TRUE(BTF.findFieldReloc({0, 1}));988 EXPECT_TRUE(BTF.findFieldReloc({8, 1}));989 EXPECT_FALSE(BTF.findFieldReloc({16, 1}));990 991 EXPECT_FALSE(BTF.findFieldReloc({0, 2}));992 EXPECT_TRUE(BTF.findFieldReloc({8, 2}));993 EXPECT_TRUE(BTF.findFieldReloc({16, 2}));994 995 EXPECT_FALSE(BTF.findFieldReloc({0, 3}));996 EXPECT_FALSE(BTF.findFieldReloc({8, 3}));997 EXPECT_FALSE(BTF.findFieldReloc({16, 3}));998 999 auto AssertReloType = [&](const SectionedAddress &A, const char *Name) {1000 const BTF::BPFFieldReloc *Relo = BTF.findFieldReloc(A);1001 ASSERT_TRUE(Relo);1002 const BTF::CommonType *Type = BTF.findType(Relo->TypeID);1003 ASSERT_TRUE(Type);1004 EXPECT_EQ(BTF.findString(Type->NameOff), Name);1005 };1006 1007 AssertReloType({8, 1}, "S");1008 AssertReloType({8, 2}, "T");1009}1010 1011TEST(BTFParserTest, parserResetReloAndTypes) {1012 BTFParser BTF;1013 MockData2 D;1014 1015 // First time: two types, two relocations.1016 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});1017 D.addType({D.addString("bar"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});1018 D.addRelocSec({D.addString("foo"), 0});1019 D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});1020 D.addReloc({8, 2, D.addString(""), BTF::TYPE_EXISTENCE});1021 1022 Error E1 = BTF.parse(D.makeObj());1023 EXPECT_FALSE(E1);1024 1025 ASSERT_TRUE(BTF.findType(1));1026 EXPECT_EQ(BTF.findString(BTF.findType(1)->NameOff), "foo");1027 EXPECT_TRUE(BTF.findType(2));1028 EXPECT_TRUE(BTF.findFieldReloc({0, 1}));1029 EXPECT_TRUE(BTF.findFieldReloc({8, 1}));1030 1031 // Second time: one type, one relocation.1032 D.reset();1033 D.addType({D.addString("buz"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});1034 D.addRelocSec({D.addString("foo"), 0});1035 D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});1036 1037 Error E2 = BTF.parse(D.makeObj());1038 EXPECT_FALSE(E2);1039 1040 ASSERT_TRUE(BTF.findType(1));1041 EXPECT_EQ(BTF.findString(BTF.findType(1)->NameOff), "buz");1042 EXPECT_FALSE(BTF.findType(2));1043 EXPECT_TRUE(BTF.findFieldReloc({0, 1}));1044 EXPECT_FALSE(BTF.findFieldReloc({8, 1}));1045}1046 1047TEST(BTFParserTest, selectiveLoad) {1048 BTFParser BTF1, BTF2, BTF3;1049 MockData2 D;1050 1051 D.addType({D.addString("foo"), mkInfo(BTF::BTF_KIND_STRUCT), {0}});1052 D.addRelocSec({D.addString("foo"), 0});1053 D.addReloc({0, 1, D.addString(""), BTF::TYPE_EXISTENCE});1054 D.addLinesSec({D.addString("foo"), 0});1055 D.addLine({0, D.addString("file.c"), D.addString("some line"), LC(2, 3)});1056 1057 BTFParser::ParseOptions Opts;1058 1059 ObjectFile &Obj1 = D.makeObj();1060 Opts = {};1061 Opts.LoadLines = true;1062 ASSERT_SUCCEEDED(BTF1.parse(Obj1, Opts));1063 1064 Opts = {};1065 Opts.LoadTypes = true;1066 ASSERT_SUCCEEDED(BTF2.parse(Obj1, Opts));1067 1068 Opts = {};1069 Opts.LoadRelocs = true;1070 ASSERT_SUCCEEDED(BTF3.parse(Obj1, Opts));1071 1072 EXPECT_TRUE(BTF1.findLineInfo({0, 1}));1073 EXPECT_FALSE(BTF2.findLineInfo({0, 1}));1074 EXPECT_FALSE(BTF3.findLineInfo({0, 1}));1075 1076 EXPECT_FALSE(BTF1.findType(1));1077 EXPECT_TRUE(BTF2.findType(1));1078 EXPECT_FALSE(BTF3.findType(1));1079 1080 EXPECT_FALSE(BTF1.findFieldReloc({0, 1}));1081 EXPECT_FALSE(BTF2.findFieldReloc({0, 1}));1082 EXPECT_TRUE(BTF3.findFieldReloc({0, 1}));1083}1084 1085} // namespace1086