forked from OSchip/llvm-project
[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:
parent
51914d5a52
commit
dc1c43d726
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue