[BPF] Add BTF 64bit enum value support

Current BTF only supports 32-bit value. For example,
  enum T { VAL = 0xffffFFFF00000008 };
the generated BTF looks like
        .long   16                              # BTF_KIND_ENUM(id = 4)
        .long   100663297                       # 0x6000001
        .long   8
        .long   18
        .long   8
The encoded value is 8 which equals to (uint32_t)0xffffFFFF00000008
and this is incorrect.

This patch introduced BTF_KIND_ENUM64 which permits to encode
64-bit value. The format for each enumerator looks like:
        .long   name_offset
        .long   (uint32_t)value # lower-32 bit value
        .long   value >> 32     # high-32 bit value

We use two 32-bit values to represent a 64-bit value as current
BTF type subsection has 4-byte alignment and gaps are not permitted
in the subsection.

This patch also added support for kflag (the bit 31 of CommonType.Info)
such that kflag = 1 implies the value is signed and kflag = 0
implies the value is unsigned. The kernel UAPI enumerator definition is
  struct btf_enum {
        __u32   name_off;
        __s32   val;
  };
so kflag = 0 with unsigned value provides backward compatability.

With this patch, for
  enum T { VAL = 0xffffFFFF00000008 };
the generated BTF looks like
        .long   16                              # BTF_KIND_ENUM64(id = 4)
        .long   3187671053                      # 0x13000001
        .long   8
        .long   18
        .long   8                               # 0x8
        .long   4294967295                      # 0xffffffff
and the enumerator value and signedness are encoded correctly.

Differential Revision: https://reviews.llvm.org/D124641
This commit is contained in:
Yonghong Song 2022-04-20 15:07:08 -07:00
parent 51914d5a52
commit dc1c43d726
7 changed files with 113 additions and 9 deletions

View File

@ -33,5 +33,6 @@ HANDLE_BTF_KIND(15, DATASEC)
HANDLE_BTF_KIND(16, FLOAT)
HANDLE_BTF_KIND(17, DECL_TAG)
HANDLE_BTF_KIND(18, TYPE_TAG)
HANDLE_BTF_KIND(19, ENUM64)
#undef HANDLE_BTF_KIND

View File

@ -60,6 +60,7 @@ enum {
CommonTypeSize = 12,
BTFArraySize = 12,
BTFEnumSize = 8,
BTFEnum64Size = 12,
BTFMemberSize = 12,
BTFParamSize = 8,
BTFDataSecVarSize = 12,
@ -145,6 +146,15 @@ struct BTFEnum {
int32_t Val; ///< Enum member value
};
/// BTF_KIND_ENUM64 is followed by multiple "struct BTFEnum64".
/// The exact number of BTFEnum64 is stored in the vlen (of the
/// info in "struct CommonType").
struct BTFEnum64 {
uint32_t NameOff; ///< Enum name offset in the string table
uint32_t Val_Lo32; ///< Enum member lo32 value
uint32_t Val_Hi32; ///< Enum member hi32 value
};
/// BTF_KIND_ARRAY is followed by one "struct BTFArray".
struct BTFArray {
uint32_t ElemType; ///< Element type

View File

@ -162,9 +162,10 @@ void BTFTypeInt::emitType(MCStreamer &OS) {
OS.emitInt32(IntVal);
}
BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen) : ETy(ETy) {
BTFTypeEnum::BTFTypeEnum(const DICompositeType *ETy, uint32_t VLen,
bool IsSigned) : ETy(ETy) {
Kind = BTF::BTF_KIND_ENUM;
BTFType.Info = Kind << 24 | VLen;
BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;
BTFType.Size = roundupToBytes(ETy->getSizeInBits());
}
@ -200,6 +201,48 @@ void BTFTypeEnum::emitType(MCStreamer &OS) {
}
}
BTFTypeEnum64::BTFTypeEnum64(const DICompositeType *ETy, uint32_t VLen,
bool IsSigned) : ETy(ETy) {
Kind = BTF::BTF_KIND_ENUM64;
BTFType.Info = IsSigned << 31 | Kind << 24 | VLen;
BTFType.Size = roundupToBytes(ETy->getSizeInBits());
}
void BTFTypeEnum64::completeType(BTFDebug &BDebug) {
if (IsCompleted)
return;
IsCompleted = true;
BTFType.NameOff = BDebug.addString(ETy->getName());
DINodeArray Elements = ETy->getElements();
for (const auto Element : Elements) {
const auto *Enum = cast<DIEnumerator>(Element);
struct BTF::BTFEnum64 BTFEnum;
BTFEnum.NameOff = BDebug.addString(Enum->getName());
uint64_t Value;
if (Enum->isUnsigned())
Value = static_cast<uint64_t>(Enum->getValue().getZExtValue());
else
Value = static_cast<uint64_t>(Enum->getValue().getSExtValue());
BTFEnum.Val_Lo32 = Value;
BTFEnum.Val_Hi32 = Value >> 32;
EnumValues.push_back(BTFEnum);
}
}
void BTFTypeEnum64::emitType(MCStreamer &OS) {
BTFTypeBase::emitType(OS);
for (const auto &Enum : EnumValues) {
OS.emitInt32(Enum.NameOff);
OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Lo32));
OS.emitInt32(Enum.Val_Lo32);
OS.AddComment("0x" + Twine::utohexstr(Enum.Val_Hi32));
OS.emitInt32(Enum.Val_Hi32);
}
}
BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t NumElems) {
Kind = BTF::BTF_KIND_ARRAY;
BTFType.NameOff = 0;
@ -674,8 +717,25 @@ void BTFDebug::visitEnumType(const DICompositeType *CTy, uint32_t &TypeId) {
if (VLen > BTF::MAX_VLEN)
return;
auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen);
bool IsSigned = false;
unsigned NumBits = 32;
// No BaseType implies forward declaration in which case a
// BTFTypeEnum with Vlen = 0 is emitted.
if (CTy->getBaseType() != nullptr) {
const auto *BTy = cast<DIBasicType>(CTy->getBaseType());
IsSigned = BTy->getEncoding() == dwarf::DW_ATE_signed ||
BTy->getEncoding() == dwarf::DW_ATE_signed_char;
NumBits = BTy->getSizeInBits();
}
if (NumBits <= 32) {
auto TypeEntry = std::make_unique<BTFTypeEnum>(CTy, VLen, IsSigned);
TypeId = addType(std::move(TypeEntry), CTy);
} else {
assert(NumBits == 64);
auto TypeEntry = std::make_unique<BTFTypeEnum64>(CTy, VLen, IsSigned);
TypeId = addType(std::move(TypeEntry), CTy);
}
// No need to visit base type as BTF does not encode it.
}

View File

@ -103,7 +103,7 @@ class BTFTypeEnum : public BTFTypeBase {
std::vector<struct BTF::BTFEnum> EnumValues;
public:
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues);
BTFTypeEnum(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned);
uint32_t getSize() override {
return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnumSize;
}
@ -218,6 +218,20 @@ public:
void emitType(MCStreamer &OS) override;
};
/// Handle 64-bit enumerate type.
class BTFTypeEnum64 : public BTFTypeBase {
const DICompositeType *ETy;
std::vector<struct BTF::BTFEnum64> EnumValues;
public:
BTFTypeEnum64(const DICompositeType *ETy, uint32_t NumValues, bool IsSigned);
uint32_t getSize() override {
return BTFTypeBase::getSize() + EnumValues.size() * BTF::BTFEnum64Size;
}
void completeType(BTFDebug &BDebug) override;
void emitType(MCStreamer &OS) override;
};
class BTFTypeTypeTag : public BTFTypeBase {
const DIDerivedType *DTy;
StringRef Tag;

View File

@ -22,7 +22,7 @@
; CHECK-NEXT: .long 28
; CHECK-NEXT: .long 5
; CHECK-NEXT: .long 0 # BTF_KIND_ENUM(id = 1)
; CHECK-NEXT: .long 100663298 # 0x6000002
; CHECK-NEXT: .long 2248146946 # 0x86000002
; CHECK-NEXT: .long 4
; CHECK-NEXT: .long 1
; CHECK-NEXT: .long -1

View File

@ -36,7 +36,7 @@ entry:
; CHECK: r{{[0-9]+}} = -2147483648 ll
; CHECK: exit
; CHECK: .long 16 # BTF_KIND_ENUM(id = 4)
; CHECK: .long 16 # BTF_KIND_ENUM64(id = 4)
; CHECK: .long 57 # BTF_KIND_TYPEDEF(id = 5)
; CHECK: .ascii ".text" # string offset=10

View File

@ -36,14 +36,33 @@ entry:
; CHECK: r{{[0-9]+}} = -2147483648 ll
; CHECK: exit
; CHECK: .long 16 # BTF_KIND_ENUM(id = 4)
; CHECK: .long 57 # BTF_KIND_TYPEDEF(id = 5)
; CHECK: .long 16 # BTF_KIND_ENUM64(id = 4)
; CHECK-NEXT: .long 2466250754 # 0x93000002
; CHECK-NEXT: .long 8
; CHECK-NEXT: .long 19
; CHECK-NEXT: .long 4294967196 # 0xffffff9c
; CHECK-NEXT: .long 4294967295 # 0xffffffff
; CHECK-NEXT: .long 24
; CHECK-NEXT: .long 4294934528 # 0xffff8000
; CHECK-NEXT: .long 0 # 0x0
; CHECK-NEXT: .long 57 # BTF_KIND_TYPEDEF(id = 5)
; CHECK-NEXT: .long 134217728 # 0x8000000
; CHECK-NEXT: .long 6
; CHECK-NEXT: .long 0 # BTF_KIND_ENUM64(id = 6)
; CHECK-NEXT: .long 318767105 # 0x13000001
; CHECK-NEXT: .long 8
; CHECK-NEXT: .long 62
; CHECK-NEXT: .long 2147483648 # 0x80000000
; CHECK-NEXT: .long 4294967295 # 0xffffffff
; CHECK: .ascii ".text" # string offset=10
; CHECK: .ascii "AA" # string offset=16
; CHECK: .ascii "VAL1" # string offset=19
; CHECK: .ascii "VAL2" # string offset=24
; CHECK: .byte 48 # string offset=29
; CHECK: .byte 49 # string offset=55
; CHECK: .ascii "__BB" # string offset=57
; CHECK: .ascii "VAL10" # string offset=62
; CHECK: .long 16 # FieldReloc
; CHECK-NEXT: .long 10 # Field reloc section string offset=10