brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.4 KiB · 7bcc709 Raw
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