Skip to content

Commit d15f96f

Browse files
committed
[BPF][DebugInfo] Show CO-RE relocations in llvm-objdump
Extend llvm-objdump to show CO-RE relocations when `-r` option is passed and object file has .BTF and .BTF.ext sections. For example, the following C program: #define __pai __attribute__((preserve_access_index)) struct foo { int i; int j;} __pai; struct bar { struct foo f[7]; } __pai; extern void sink(void *); void root(struct bar *bar) { sink(&bar[2].f[3].j); } Should lead to the following objdump output: $ clang --target=bpf -O2 -g t.c -c -o - | \ llvm-objdump --no-addresses --no-show-raw-insn -dr - ... r2 = 0x94 CO-RE <byte_off> [2] struct bar::[2].f[3].j (2:0:3:1) r1 += r2 call -0x1 R_BPF_64_32 sink exit ... More examples could be found in unit tests, see BTFParserTest.cpp. To achieve this: - Move CO-RE relocation kinds definitions from BPFCORE.h to BTF.h. - Extend BTF.h with types derived from BTF::CommonType, e.g. BTF::IntType and BTF::StrutType, to allow dyn_cast() and access to type additional data. - Extend BTFParser to load BTF type and relocation data. - Modify llvm-objdump.cpp to create instance of BTFParser when disassembly of object file with BTF sections is processed and `-r` flag is supplied. Additional information about CO-RE is available at [1]. [1] https://docs.kernel.org/bpf/llvm_reloc.html Depends on D149058 Differential Revision: https://reviews.llvm.org/D150079
1 parent 4dec62f commit d15f96f

17 files changed

+2714
-85
lines changed

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

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
#ifndef LLVM_LIB_TARGET_BPF_BTF_H
4949
#define LLVM_LIB_TARGET_BPF_BTF_H
5050

51-
#include <cstdint>
51+
#include "llvm/ADT/ArrayRef.h"
52+
#include "llvm/Support/TrailingObjects.h"
5253

5354
namespace llvm {
5455
namespace BTF {
@@ -97,6 +98,10 @@ enum TypeKinds : uint8_t {
9798
#include "BTF.def"
9899
};
99100

101+
// Constants for CommonType::Info field.
102+
constexpr uint32_t FWD_UNION_FLAG = 1u << 31;
103+
constexpr uint32_t ENUM_SIGNED_FLAG = 1u << 31;
104+
100105
/// The BTF common type definition. Different kinds may have
101106
/// additional information after this structure data.
102107
struct CommonType {
@@ -106,8 +111,8 @@ struct CommonType {
106111
/// "Info" bits arrangement:
107112
/// Bits 0-15: vlen (e.g. # of struct's members)
108113
/// Bits 16-23: unused
109-
/// Bits 24-27: kind (e.g. int, ptr, array...etc)
110-
/// Bits 28-30: unused
114+
/// Bits 24-28: kind (e.g. int, ptr, array...etc)
115+
/// Bits 29-30: unused
111116
/// Bit 31: kind_flag, currently used by
112117
/// struct, union and fwd
113118
uint32_t Info;
@@ -122,6 +127,9 @@ struct CommonType {
122127
uint32_t Size;
123128
uint32_t Type;
124129
};
130+
131+
uint32_t getKind() const { return Info >> 24 & 0x1f; }
132+
uint32_t getVlen() const { return Info & 0xffff; }
125133
};
126134

127135
// For some specific BTF_KIND, "struct CommonType" is immediately
@@ -269,6 +277,84 @@ struct SecFieldReloc {
269277
uint32_t NumFieldReloc; ///< Number of offset reloc's in this section
270278
};
271279

280+
/// CO-RE relocation kind codes used in .BTF.ext section.
281+
enum PatchableRelocKind : uint32_t {
282+
FIELD_BYTE_OFFSET = 0,
283+
FIELD_BYTE_SIZE,
284+
FIELD_EXISTENCE,
285+
FIELD_SIGNEDNESS,
286+
FIELD_LSHIFT_U64,
287+
FIELD_RSHIFT_U64,
288+
BTF_TYPE_ID_LOCAL,
289+
BTF_TYPE_ID_REMOTE,
290+
TYPE_EXISTENCE,
291+
TYPE_SIZE,
292+
ENUM_VALUE_EXISTENCE,
293+
ENUM_VALUE,
294+
TYPE_MATCH,
295+
MAX_FIELD_RELOC_KIND,
296+
};
297+
298+
// Define a number of sub-types for CommonType, each with:
299+
// - An accessor for a relevant "tail" information (data fields that
300+
// follow the CommonType record in binary format).
301+
// - A classof() definition based on CommonType::getKind() value to
302+
// allow use with dyn_cast<>() function.
303+
304+
// For CommonType sub-types that are followed by a single entry of
305+
// some type in the binary format.
306+
#define BTF_DEFINE_TAIL(Type, Accessor) \
307+
const Type &Accessor() const { return *getTrailingObjects<Type>(); }
308+
309+
// For CommonType sub-types that are followed by CommonType::getVlen()
310+
// number of entries of some type in the binary format.
311+
#define BTF_DEFINE_TAIL_ARR(Type, Accessor) \
312+
ArrayRef<Type> Accessor() const { \
313+
return ArrayRef<Type>(getTrailingObjects<Type>(), getVlen()); \
314+
}
315+
316+
struct ArrayType final : CommonType,
317+
private TrailingObjects<ArrayType, BTFArray> {
318+
friend TrailingObjects;
319+
BTF_DEFINE_TAIL(BTFArray, getArray)
320+
321+
static bool classof(const CommonType *V) {
322+
return V->getKind() == BTF_KIND_ARRAY;
323+
}
324+
};
325+
326+
struct StructType final : CommonType,
327+
private TrailingObjects<StructType, BTFMember> {
328+
friend TrailingObjects;
329+
BTF_DEFINE_TAIL_ARR(BTFMember, members)
330+
331+
static bool classof(const CommonType *V) {
332+
return V->getKind() == BTF_KIND_STRUCT || V->getKind() == BTF_KIND_UNION;
333+
}
334+
};
335+
336+
struct EnumType final : CommonType, private TrailingObjects<EnumType, BTFEnum> {
337+
friend TrailingObjects;
338+
BTF_DEFINE_TAIL_ARR(BTFEnum, values)
339+
340+
static bool classof(const CommonType *V) {
341+
return V->getKind() == BTF_KIND_ENUM;
342+
}
343+
};
344+
345+
struct Enum64Type final : CommonType,
346+
private TrailingObjects<Enum64Type, BTFEnum64> {
347+
friend TrailingObjects;
348+
BTF_DEFINE_TAIL_ARR(BTFEnum64, values)
349+
350+
static bool classof(const CommonType *V) {
351+
return V->getKind() == BTF_KIND_ENUM64;
352+
}
353+
};
354+
355+
#undef BTF_DEFINE_TAIL
356+
#undef BTF_DEFINE_TAIL_ARR
357+
272358
} // End namespace BTF.
273359
} // End namespace llvm.
274360

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
// BPF backend and provides introspection for the stored information.
1111
// Currently the following information is accessible:
1212
// - string table;
13-
// - instruction offset to line information mapping.
13+
// - instruction offset to line information mapping;
14+
// - types table;
15+
// - CO-RE relocations table.
1416
//
1517
// See llvm/DebugInfo/BTF/BTF.h for some details about binary format
1618
// and links to Linux Kernel documentation.
@@ -32,22 +34,42 @@ using object::SectionRef;
3234

3335
class BTFParser {
3436
using BTFLinesVector = SmallVector<BTF::BPFLineInfo, 0>;
37+
using BTFRelocVector = SmallVector<BTF::BPFFieldReloc, 0>;
3538

3639
// In BTF strings are stored as a continuous memory region with
3740
// individual strings separated by 0 bytes. Strings are identified
3841
// by an offset in such region.
3942
// The `StringsTable` points to this region in the parsed ObjectFile.
4043
StringRef StringsTable;
4144

45+
// A copy of types table from the object file but using native byte
46+
// order. Should not be too big in practice, e.g. for ~250MiB vmlinux
47+
// image it is ~4MiB.
48+
OwningArrayRef<uint8_t> TypesBuffer;
49+
4250
// Maps ELF section number to instruction line number information.
4351
// Each BTFLinesVector is sorted by `InsnOffset` to allow fast lookups.
4452
DenseMap<uint64_t, BTFLinesVector> SectionLines;
4553

54+
// Maps ELF section number to CO-RE relocation information.
55+
// Each BTFRelocVector is sorted by `InsnOffset` to allow fast lookups.
56+
DenseMap<uint64_t, BTFRelocVector> SectionRelocs;
57+
58+
// Vector of pointers to all known types, index in this vector
59+
// equals to logical type BTF id.
60+
// Pointers point to memory owned by `TypesBuffer`
61+
// (except pointer at index 0, which is statically allocated).
62+
std::vector<const BTF::CommonType *> Types;
63+
4664
struct ParseContext;
4765
Error parseBTF(ParseContext &Ctx, SectionRef BTF);
4866
Error parseBTFExt(ParseContext &Ctx, SectionRef BTFExt);
4967
Error parseLineInfo(ParseContext &Ctx, DataExtractor &Extractor,
5068
uint64_t LineInfoStart, uint64_t LineInfoEnd);
69+
Error parseRelocInfo(ParseContext &Ctx, DataExtractor &Extractor,
70+
uint64_t RelocInfoStart, uint64_t RelocInfoEnd);
71+
Error parseTypesInfo(ParseContext &Ctx, uint64_t TypesInfoStart,
72+
StringRef RawData);
5173

5274
public:
5375
// Looks-up a string in the .BTF section's string table.
@@ -61,6 +83,34 @@ class BTFParser {
6183
// owned by this class.
6284
const BTF::BPFLineInfo *findLineInfo(SectionedAddress Address) const;
6385

86+
// Search for CO-RE relocation information for a specific address.
87+
// Return nullptr if no information found.
88+
// If information is present, return a pointer to object
89+
// owned by this class.
90+
const BTF::BPFFieldReloc *findFieldReloc(SectionedAddress Address) const;
91+
92+
// Return a human readable representation of the CO-RE relocation
93+
// record, this is for display purpose only.
94+
// See implementation for details.
95+
void symbolize(const BTF::BPFFieldReloc *Reloc,
96+
SmallVectorImpl<char> &Result) const;
97+
98+
// Lookup BTF type definition with a specific index.
99+
// Return nullptr if no information found.
100+
// If information is present, return a pointer to object
101+
// owned by this class.
102+
const BTF::CommonType *findType(uint32_t Id) const;
103+
104+
// Return total number of known BTF types.
105+
size_t typesCount() const { return Types.size(); }
106+
107+
// Allow to selectively load BTF information.
108+
struct ParseOptions {
109+
bool LoadLines = false;
110+
bool LoadTypes = false;
111+
bool LoadRelocs = false;
112+
};
113+
64114
// Fills instance of BTFParser with information stored in .BTF and
65115
// .BTF.ext sections of the `Obj`. If this instance was already
66116
// filled, old data is discarded.
@@ -70,7 +120,8 @@ class BTFParser {
70120
// - state of the BTFParser might be incomplete but is not invalid,
71121
// queries might be run against it, but some (or all) information
72122
// might be unavailable;
73-
Error parse(const ObjectFile &Obj);
123+
Error parse(const ObjectFile &Obj, const ParseOptions &Opts);
124+
Error parse(const ObjectFile &Obj) { return parse(Obj, {true, true, true}); }
74125

75126
// Return true if `Obj` has .BTF and .BTF.ext sections.
76127
static bool hasBTFSections(const ObjectFile &Obj);

llvm/lib/DebugInfo/BTF/BTFContext.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ std::unique_ptr<BTFContext>
6363
BTFContext::create(const ObjectFile &Obj,
6464
std::function<void(Error)> ErrorHandler) {
6565
auto Ctx = std::make_unique<BTFContext>();
66-
if (Error E = Ctx->BTF.parse(Obj))
66+
BTFParser::ParseOptions Opts;
67+
Opts.LoadLines = true;
68+
if (Error E = Ctx->BTF.parse(Obj, Opts))
6769
ErrorHandler(std::move(E));
6870
return Ctx;
6971
}

0 commit comments

Comments
 (0)