Index: include/llvm/MC/MCBTF.def =================================================================== --- /dev/null +++ include/llvm/MC/MCBTF.def @@ -0,0 +1,33 @@ +//===- llvm/MC/MCBTF.def - BTF definitions ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for BTF. +// +//===----------------------------------------------------------------------===// + +#if !defined(HANDLE_BTF_KIND) +#error "Missing macro definition of HANDLE_BTF_*" +#endif + +HANDLE_BTF_KIND(0, UNKN) +HANDLE_BTF_KIND(1, INT) +HANDLE_BTF_KIND(2, PTR) +HANDLE_BTF_KIND(3, ARRAY) +HANDLE_BTF_KIND(4, STRUCT) +HANDLE_BTF_KIND(5, UNION) +HANDLE_BTF_KIND(6, ENUM) +HANDLE_BTF_KIND(7, FWD) +HANDLE_BTF_KIND(8, TYPEDEF) +HANDLE_BTF_KIND(9, VOLATILE) +HANDLE_BTF_KIND(10, CONST) +HANDLE_BTF_KIND(11, RESTRICT) +HANDLE_BTF_KIND(12, FUNC) +HANDLE_BTF_KIND(13, FUNC_PROTO) + +#undef HANDLE_BTF_KIND Index: include/llvm/MC/MCBTFContext.h =================================================================== --- /dev/null +++ include/llvm/MC/MCBTFContext.h @@ -0,0 +1,345 @@ +//===- MCBTFContext.h ---------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the layout of .BTF and .BTF.ext ELF sections, +/// and C++ classes to generate these two sections. +/// +/// The binary layout for .BTF section: +/// struct BTFHeader +/// Type and Str subsections +/// The Type subsection is a collection of types with type id starting with 1. +/// The Str subsection is simply a collection of strings. +/// +/// The binary layout for .BTF.ext section: +/// struct BTFExtHeader +/// FuncInfo and LineInfo subsections +/// The FuncInfo subsection is defined as below: +/// struct BTFSecFuncInfo for ELF section #1 +/// A number of struct BPFFuncInfo for ELF section #1 +/// struct BTFSecFuncInfo for ELF section #2 +/// A number of struct BPFFuncInfo for ELF section #2 +/// ... +/// The LineInfo subsection is defined as below: +/// struct BTFSecLineInfo for ELF section #1 +/// A number of struct BPFLineInfo for ELF section #1 +/// struct BTFSecLineInfo for ELF section #2 +/// A number of struct BPFLineInfo for ELF section #2 +/// ... +/// +/// The section formats are also defined at +/// https://github.com/torvalds/linux/blob/master/include/uapi/linux/btf.h +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCBTFCONTEXT_H +#define LLVM_MC_MCBTFCONTEXT_H + +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { + +enum BTFHeaderValues { BTF_MAGIC = 0xeB9F, BTF_VERSION = 1 }; + +/// The .BTF section header definition +struct BTFHeader { + uint16_t Magic; ///< Magic value + uint8_t Version; ///< Version number + uint8_t Flags; ///< Extra flags + uint32_t HdrLen; ///< Length of this header + + /// All offsets are in bytes relative to the end of this header + uint32_t TypeOff; ///< Offset of type section + uint32_t TypeLen; ///< Length of type section + uint32_t StrOff; ///< Offset of string section + uint32_t StrLen; ///< Length of string section +}; + +enum BTFLimits { + BTF_MAX_TYPE = 0xffff, ///< Max # of type identifier + BTF_MAX_NAME_OFFSET = 0xffff, ///< Max offset into the string section + BTF_MAX_VLEN = 0xffff ///< Max # of struct/union/enum members or func args +}; + +/// The BTF common type definition. Different kinds may have +/// additional information after this structure data. +struct BTFType { + /// Type name offset in the string table + uint32_t NameOff; + + /// "Info" bits arrangement + /// Bits 0-15: vlen (e.g. # of struct's members) + /// Bits 16-23: unused + /// Bits 24-27: kind (e.g. int, ptr, array...etc) + /// Bits 28-31: unused + uint32_t Info; + + /// "Size" is used by INT, ENUM, STRUCT and UNION. + /// "Size" tells the size of the type it is describing. + /// + /// "Type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, + /// FUNC and FUNC_PROTO. + /// "Type" is a type_id referring to another type. + union { + uint32_t Size; + uint32_t Type; + }; +}; + +enum BTFTypeKinds { +#define HANDLE_BTF_KIND(ID, NAME) BTF_KIND_##NAME = ID, +#include "llvm/MC/MCBTF.def" +}; + +// For some specific BTF_KIND, "struct BTFType" is immediately +// followed by extra data. + +// BTF_KIND_INT is followed by a u32 and the following +// is the 32 bits arrangement: +// BTF_INT_ENCODING(VAL) : (((VAL) & 0x0f000000) >> 24) +// BTF_INT_OFFSET(VAL) : (((VAL & 0x00ff0000)) >> 16) +// BTF_INT_BITS(VAL) : ((VAL) & 0x000000ff) + +/// Attributes stored in the BTF_INT_ENCODING +enum BTFIntEncoding { + BTF_INT_SIGNED = (1 << 0), + BTF_INT_CHAR = (1 << 1), + BTF_INT_BOOL = (1 << 2) +}; + +/// BTF_KIND_ENUM is followed by multiple "struct btf_enum". +/// The exact number of btf_enum is stored in the vlen (of the +/// info in "struct BTFType"). +struct BTFEnum { + uint32_t NameOff; ///< Enum name offset in the string table + int32_t Val; ///< Enum member value +}; + +/// BTF_KIND_ARRAY is followed by one "struct btf_array" +struct BTFArray { + uint32_t ElemType; ///< Element type + uint32_t IndexType; ///< Index type + uint32_t Nelems; ///< Number of elements for this array +}; + +/// BTF_KIND_STRUCT and BTF_KIND_UNION are followed +/// by multiple "struct BTFMember". The exact number +/// of BTFMember is stored in the vlen (of the info in +/// "struct BTFType"). +struct BTFMember { + uint32_t NameOff; ///< Member name offset in the string table + uint32_t Type; ///< Member type + uint32_t Offset; ///< Offset in bits from the struct start +}; + +/// The .BTF.ext section header definition +struct BTFExtHeader { + uint16_t Magic; + uint8_t Version; + uint8_t Flags; + uint32_t HdrLen; + + uint32_t FuncInfoOff; ///< Offset of func info section + uint32_t FuncInfoLen; ///< Length of func info section + uint32_t LineInfoOff; ///< Offset of line info section + uint32_t LineInfoLen; ///< Length of line info section +}; + +/// Specifying one function info +struct BPFFuncInfo { + uint32_t InsnOffset; ///< Byte offset in the section + uint32_t TypeId; ///< Type id referring to .BTF type section +}; + +/// Specifying function info's in one section +struct BTFSecFuncInfo { + uint32_t SecNameOff; ///< Section name index in the .BTF string table + uint32_t NumFuncInfo; ///< Number of func info's in this section +}; + +/// Specifying one line info +struct BPFLineInfo { + uint32_t InsnOffset; ///< Byte offset in this section + uint32_t FileNameOff; ///< File name index in the .BTF string table + uint32_t LineOff; ///< Line index in the .BTF string table + uint32_t LineCol; ///< Line num: line_col >> 10, + /// col num: line_col & 0x3ff +}; + +/// Specifying line info's in one section +struct BTFSecLineInfo { + uint32_t SecNameOff; ///< Section name index in the .BTF string tble + uint32_t NumLineInfo; ///< Number of line info's in this section +}; + +class MCBTFContext; +class MCObjectStreamer; + +/// This is base class of all BTF KIND. It is also used directly +/// by the reference kinds: +/// BTF_KIND_CONST, BTF_KIND_PTR, BTF_KIND_VOLATILE, +/// BTF_KIND_TYPEDEF, BTF_KIND_RESTRICT, and BTF_KIND_FWD +class BTFTypeEntry { +protected: + size_t Id; ///< type index in the BTF list, started from 1 + struct BTFType BTFType; + +public: + BTFTypeEntry(size_t Id, struct BTFType &Type) : Id(Id), BTFType(Type) {} + virtual ~BTFTypeEntry(); + uint8_t getKind() { return (BTFType.Info >> 24) & 0x0f; } + uint16_t getVlen() { return BTFType.Info & 0xffff; } + + virtual size_t getSize() { return sizeof(struct BTFType); } + virtual void print(raw_ostream &OS, MCBTFContext &BTFContext); + virtual void emitData(MCObjectStreamer *MCOS); +}; + +/// Type entry for BTF_KIND_INT +class BTFTypeEntryInt : public BTFTypeEntry { + unsigned IntVal; ///< encoding, offset, bits + +public: + BTFTypeEntryInt(size_t Id, struct BTFType &Type, unsigned Intval) + : BTFTypeEntry(Id, Type), IntVal(Intval) {} + size_t getSize() { return BTFTypeEntry::getSize() + sizeof(unsigned); } + void print(raw_ostream &OS, MCBTFContext &BTFContext); + void emitData(MCObjectStreamer *MCOS); +}; + +/// Type entry for BTF_KIND_ENUM +class BTFTypeEntryEnum : public BTFTypeEntry { + std::vector EnumValues; + +public: + BTFTypeEntryEnum(size_t Id, struct BTFType &Type, + std::vector &Values) + : BTFTypeEntry(Id, Type), EnumValues(Values) {} + size_t getSize() { + return BTFTypeEntry::getSize() + getVlen() * sizeof(struct BTFEnum); + } + void print(raw_ostream &OS, MCBTFContext &BTFContext); + void emitData(MCObjectStreamer *MCOS); +}; + +/// Type entry for BTF_KIND_ARRAY +class BTFTypeEntryArray : public BTFTypeEntry { + struct BTFArray ArrayInfo; + +public: + BTFTypeEntryArray(size_t Id, struct BTFType &Type, struct BTFArray &Arrayinfo) + : BTFTypeEntry(Id, Type), ArrayInfo(Arrayinfo) {} + size_t getSize() { return BTFTypeEntry::getSize() + sizeof(struct BTFArray); } + void print(raw_ostream &OS, MCBTFContext &BTFContext); + void emitData(MCObjectStreamer *MCOS); +}; + +/// Type entry for BTF_KIND_STRUCT and BTF_KIND_UNION +class BTFTypeEntryStruct : public BTFTypeEntry { + std::vector Members; + +public: + BTFTypeEntryStruct(size_t Id, struct BTFType &Type, + std::vector &Members) + : BTFTypeEntry(Id, Type), Members(Members) {} + size_t getSize() { + return BTFTypeEntry::getSize() + getVlen() * sizeof(struct BTFMember); + } + void print(raw_ostream &OS, MCBTFContext &BTFContext); + void emitData(MCObjectStreamer *MCOS); +}; + +/// Type entry for BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO +class BTFTypeEntryFunc : public BTFTypeEntry { + std::vector Parameters; + +public: + BTFTypeEntryFunc(size_t Id, struct BTFType &Type, + std::vector &Params) + : BTFTypeEntry(Id, Type), Parameters(Params) {} + size_t getSize() { + return BTFTypeEntry::getSize() + getVlen() * sizeof(unsigned); + } + void print(raw_ostream &OS, MCBTFContext &BTFContext); + void emitData(MCObjectStreamer *MCOS); +}; + +/// String table +class BTFStringTable { + size_t Size; ///< total size in bytes + std::map OffsetToIdMap; + std::vector Table; + +public: + BTFStringTable() : Size(0) {} + size_t getSize() { return Size; } + std::vector &getTable() { return Table; } + size_t addString(std::string S) { + // check whether the string already exists + for (auto &OffsetM : OffsetToIdMap) { + if (Table[OffsetM.second] == S) + return OffsetM.first; + } + // not find, add to the string table + size_t Offset = Size; + OffsetToIdMap[Offset] = Table.size(); + Table.push_back(S); + Size += S.size() + 1; + return Offset; + } + void showTable(raw_ostream &OS) { + for (auto OffsetM : OffsetToIdMap) + OS << OffsetM.first << " : " << Table[OffsetM.second] << "\n"; + } +}; + +/// Representing one func and its type id +struct BTFFuncInfo { + const MCSymbol *Label; ///< Func MCSymbol + unsigned int TypeId; ///< Type id referring to .BTF type section +}; + +/// Representing one func and its line info +struct BTFLineInfo { + MCSymbol *Label; ///< Func MCSymbol + unsigned int FileNameOff; ///< file name offset in the .BTF string table + unsigned int LineOff; ///< line offset in the .BTF string table + unsigned int LineNum; ///< the line number + unsigned int ColumnNum; ///< the column number +}; + +/// Capturing all info necessary to emit .BTF and .BTF.ext sections +class MCBTFContext { + std::vector> TypeEntries; + BTFStringTable StringTable; + std::map> FuncInfoTable; + std::map> LineInfoTable; + + void emitCommonHeader(MCObjectStreamer *MCOS); + void emitBTFSection(MCObjectStreamer *MCOS); + void emitBTFExtSection(MCObjectStreamer *MCOS); + +public: + void dump(raw_ostream &OS); + void emit(MCObjectStreamer *MCOS); + + void addTypeEntry(std::unique_ptr Entry); + size_t addString(std::string S) { return StringTable.addString(S); } + void addFuncInfo(unsigned SecNameOff, BTFFuncInfo Info) { + FuncInfoTable[SecNameOff].push_back(Info); + } + void addLineInfo(unsigned SecNameOff, BTFLineInfo Info) { + LineInfoTable[SecNameOff].push_back(Info); + } +}; + +} // namespace llvm +#endif Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -56,6 +56,7 @@ class MCSymbolWasm; class SMLoc; class SourceMgr; + class MCBTFContext; /// Context object for machine code objects. This class owns all of the /// sections that it creates. @@ -278,6 +279,9 @@ /// Map of currently defined macros. StringMap MacroMap; + /// Holding the BTF debug information + std::unique_ptr BTFCtx; + public: explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, @@ -286,6 +290,9 @@ MCContext &operator=(const MCContext &) = delete; ~MCContext(); + void setBTFContext(std::unique_ptr Ctx); + std::unique_ptr &getBTFContext() { return BTFCtx; } + const SourceMgr *getSourceManager() const { return SrcMgr; } void setInlineSourceManager(SourceMgr *SM) { InlineSrcMgr = SM; } Index: include/llvm/MC/MCObjectFileInfo.h =================================================================== --- include/llvm/MC/MCObjectFileInfo.h +++ include/llvm/MC/MCObjectFileInfo.h @@ -207,6 +207,12 @@ MCSection *SXDataSection; MCSection *GFIDsSection; + /// BTF specific sections. + /// @{ + MCSection *BTFSection; + MCSection *BTFExtSection; + /// @} + public: void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, bool LargeCodeModel = false); @@ -372,6 +378,10 @@ return EHFrameSection; } + // BTF specific sections. + MCSection *getBTFSection() const { return BTFSection; } + MCSection *getBTFExtSection() const { return BTFExtSection; } + enum Environment { IsMachO, IsELF, IsCOFF, IsWasm }; Environment getObjectFileType() const { return Env; } Index: include/llvm/MC/MCObjectStreamer.h =================================================================== --- include/llvm/MC/MCObjectStreamer.h +++ include/llvm/MC/MCObjectStreamer.h @@ -138,6 +138,7 @@ unsigned PointerSize); void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label); + void EmitBTFAdvanceLineAddr(const MCSymbol *Label, unsigned Size); void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc) override; Index: lib/CodeGen/AsmPrinter/CMakeLists.txt =================================================================== --- lib/CodeGen/AsmPrinter/CMakeLists.txt +++ lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -17,6 +17,7 @@ DwarfFile.cpp DwarfStringPool.cpp DwarfUnit.cpp + Dwarf2BTF.cpp EHStreamer.cpp ErlangGCPrinter.cpp OcamlGCPrinter.cpp Index: lib/CodeGen/AsmPrinter/Dwarf2BTF.h =================================================================== --- /dev/null +++ lib/CodeGen/AsmPrinter/Dwarf2BTF.h @@ -0,0 +1,140 @@ +//===- Dwarf2BTF.h -------------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARF2BTF_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARF2BTF_H + +#include "DwarfUnit.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DIE.h" +#include "llvm/MC/MCBTFContext.h" +#include + +namespace llvm { + +class Dwarf2BTF; +class MCBTFContext; + +enum BTFInvalidEncoding { BTF_INVALID_ENCODING = 0xff }; + +/// Converting a Dwarf Die to a BTF type. Each Die will have +/// a corresponding Die2BTF entry unless that Die is skipped. +class Die2BTFEntry { +protected: + const DIE &Die; + size_t Id; ///< Type index in the BTF list, started from 1 + struct BTFType BTFType; + +public: + virtual ~Die2BTFEntry(); + + /// Return desired BTF_KIND for the Die, return BTF_KIND_UNKN for + /// invalid/unsupported Die + static uint8_t getDieKind(const DIE &Die); + + /// Return proper BTF_INT_ENCODING of a basetype. + /// Return BTF_INVALID_ENCODING for unsupported (float, etc.) + static uint8_t getBaseTypeEncoding(const DIE &Die); + + /// Return whether this Die should be skipped. + /// We currently skip unsupported data type (e.g. float) + /// and references to unsupported types + static bool shouldSkipDie(const DIE &Die); + + /// Return a unique_ptr of Die2BTFEntry object for the + /// corresponding Die + static std::unique_ptr dieToBTFTypeEntry(const DIE &Die); + + Die2BTFEntry(const DIE &Die); + void setId(size_t Id) { this->Id = Id; } + size_t getId() { return Id; } + virtual void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +/// Die2BTF entry for BTF_KIND_INT +class Die2BTFEntryInt : public Die2BTFEntry { + uint32_t IntVal; // encoding, offset, bits + +public: + Die2BTFEntryInt(const DIE &Die); + void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +/// Die2BTF entry for BTF_KIND_ENUM +class Die2BTFEntryEnum : public Die2BTFEntry { + std::vector EnumValues; + +public: + Die2BTFEntryEnum(const DIE &Die); + void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +/// Die2BTF entry for BTF_KIND_ARRAY +class Die2BTFEntryArray : public Die2BTFEntry { + struct BTFArray ArrayInfo; + +public: + Die2BTFEntryArray(const DIE &Die); + void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +// Die2BTF entry for BTF_KIND_STRUCT and BTF_KIND_UNION +class Die2BTFEntryStruct : public Die2BTFEntry { + std::vector Members; + +public: + Die2BTFEntryStruct(const DIE &Die); + void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +// Die2BTF entry for BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO +class Die2BTFEntryFunc : public Die2BTFEntry { + std::vector Parameters; + bool IsFuncProto; + +public: + Die2BTFEntryFunc(const DIE &Die); + void completeData(class Dwarf2BTF &Dwarf2BTF); +}; + +/// Converting Dwarf types to BTF types and recording +/// Dwarf subprogram BTF types +class Dwarf2BTF { + std::vector> TypeEntries; + std::map DieToIdMap; + std::unique_ptr BTFContext; + MCContext &OuterCtx; + bool IsLE; + + void addTypeEntry(const DIE &Die); + bool alreadyAdded(DIE &Die) { + return DieToIdMap.find(const_cast(&Die)) != DieToIdMap.end(); + } + void completeData(); + +public: + Dwarf2BTF(MCContext &Context, bool IsLittleEndian); + bool isLittleEndian() { return IsLE; } + void addDwarfCU(DwarfUnit *TheU); + void finish(); + uint32_t getTypeIndex(DIE &Die) { + DIE *DiePtr = const_cast(&Die); + assert((DieToIdMap.find(DiePtr) != DieToIdMap.end()) && + "Die not added to in the BTFContext"); + return DieToIdMap[DiePtr]; + } + size_t addBTFString(std::string S) { return BTFContext->addString(S); } + void addBTFTypeEntry(std::unique_ptr Entry); + void addBTFFuncInfo(unsigned SecNameOff, BTFFuncInfo FuncInfo) { + BTFContext->addFuncInfo(SecNameOff, FuncInfo); + } +}; + +} // namespace llvm +#endif Index: lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp =================================================================== --- /dev/null +++ lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp @@ -0,0 +1,476 @@ +//===- Dwarf2BTF.cpp ------------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Dwarf2BTF.h" +#include "DwarfUnit.h" +#include "llvm/MC/MCBTFContext.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + +Die2BTFEntry::~Die2BTFEntry() {} + +uint8_t Die2BTFEntry::getDieKind(const DIE &Die) { + auto Tag = Die.getTag(); + + switch (Tag) { + case dwarf::DW_TAG_base_type: + if (getBaseTypeEncoding(Die) == BTF_INVALID_ENCODING) + return BTF_KIND_UNKN; + return BTF_KIND_INT; + case dwarf::DW_TAG_const_type: + return BTF_KIND_CONST; + case dwarf::DW_TAG_pointer_type: + return BTF_KIND_PTR; + case dwarf::DW_TAG_restrict_type: + return BTF_KIND_RESTRICT; + case dwarf::DW_TAG_volatile_type: + return BTF_KIND_VOLATILE; + case dwarf::DW_TAG_typedef: + return BTF_KIND_TYPEDEF; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_class_type: + if (Die.findAttribute(dwarf::DW_AT_declaration).getType() != + DIEValue::isNone) + return BTF_KIND_FWD; + else + return BTF_KIND_STRUCT; + case dwarf::DW_TAG_union_type: + if (Die.findAttribute(dwarf::DW_AT_declaration).getType() != + DIEValue::isNone) + return BTF_KIND_FWD; + else + return BTF_KIND_UNION; + case dwarf::DW_TAG_enumeration_type: + return BTF_KIND_ENUM; + case dwarf::DW_TAG_array_type: + return BTF_KIND_ARRAY; + case dwarf::DW_TAG_subprogram: + return BTF_KIND_FUNC; + case dwarf::DW_TAG_subroutine_type: + return BTF_KIND_FUNC_PROTO; + default: + break; + } + + return BTF_KIND_UNKN; +} + +std::unique_ptr Die2BTFEntry::dieToBTFTypeEntry(const DIE &Die) { + uint8_t Kind = getDieKind(Die); + + switch (Kind) { + case BTF_KIND_INT: + return llvm::make_unique(Die); + case BTF_KIND_PTR: + case BTF_KIND_TYPEDEF: + case BTF_KIND_VOLATILE: + case BTF_KIND_CONST: + case BTF_KIND_RESTRICT: + case BTF_KIND_FWD: + return llvm::make_unique(Die); + case BTF_KIND_ARRAY: + return llvm::make_unique(Die); + case BTF_KIND_STRUCT: + case BTF_KIND_UNION: + return llvm::make_unique(Die); + case BTF_KIND_ENUM: + return llvm::make_unique(Die); + case BTF_KIND_FUNC: + case BTF_KIND_FUNC_PROTO: + return llvm::make_unique(Die); + default: + break; + } + return nullptr; +} + +bool Die2BTFEntry::shouldSkipDie(const DIE &Die) { + auto Tag = Die.getTag(); + + switch (Tag) { + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_volatile_type: { + auto TypeV = Die.findAttribute(dwarf::DW_AT_type); + if (TypeV.getType() == DIEValue::isNone) + return false; + auto &TypeDie = TypeV.getDIEEntry().getEntry(); + return Die2BTFEntry::shouldSkipDie(TypeDie); + } + default: + return getDieKind(Die) == BTF_KIND_UNKN; + } + return true; +} +uint8_t Die2BTFEntry::getBaseTypeEncoding(const DIE &Die) { + auto V = Die.findAttribute(dwarf::DW_AT_encoding); + + if (V.getType() != DIEValue::isInteger) + return BTF_INVALID_ENCODING; + + switch (V.getDIEInteger().getValue()) { + case dwarf::DW_ATE_boolean: + return BTF_INT_BOOL; + case dwarf::DW_ATE_signed: + return BTF_INT_SIGNED; + case dwarf::DW_ATE_signed_char: + return BTF_INT_CHAR; + case dwarf::DW_ATE_unsigned: + return 0; + case dwarf::DW_ATE_unsigned_char: + return BTF_INT_CHAR; + case dwarf::DW_ATE_imaginary_float: + case dwarf::DW_ATE_packed_decimal: + case dwarf::DW_ATE_numeric_string: + case dwarf::DW_ATE_edited: + case dwarf::DW_ATE_signed_fixed: + case dwarf::DW_ATE_address: + case dwarf::DW_ATE_complex_float: + case dwarf::DW_ATE_float: + default: + break; + } + return BTF_INVALID_ENCODING; +} + +Die2BTFEntry::Die2BTFEntry(const DIE &Die) : Die(Die) { + uint8_t Kind = getDieKind(Die); + BTFType.Info = (Kind & 0xf) << 24; +} + +void Die2BTFEntry::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto TypeV = Die.findAttribute(dwarf::DW_AT_type); + if (TypeV.getType() == DIEValue::isNone) { + BTFType.Type = 0; + } else { + auto &TypeDie = TypeV.getDIEEntry().getEntry(); + auto Type = Dwarf2BTF.getTypeIndex(TypeDie); + BTFType.Type = Type; + } + + uint8_t Kind = getDieKind(Die); + if (Kind != BTF_KIND_FWD) { + BTFType.NameOff = 0; + } else { + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + auto Str = NameV.getDIEString().getString(); + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + } + + auto typeEntry = llvm::make_unique(Id, BTFType); + Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry)); +} + +Die2BTFEntryInt::Die2BTFEntryInt(const DIE &Die) : Die2BTFEntry(Die) { + // Handle BTF_INT_ENCODING in IntVal. + auto Encoding = Die2BTFEntry::getBaseTypeEncoding(Die); + assert((Encoding != BTF_INVALID_ENCODING) && + "Invalid Die passed to BTFTypeEntryInt()"); + uint32_t IntVal = (Encoding & 0xf) << 24; + + // Handle BTF_INT_OFFSET in IntVal. + auto V = Die.findAttribute(dwarf::DW_AT_bit_offset); + if (V.getType() == DIEValue::isInteger) + IntVal |= (V.getDIEInteger().getValue() & 0xff) << 16; + + // Get btf_type.size. + V = Die.findAttribute(dwarf::DW_AT_byte_size); + uint32_t Size = V.getDIEInteger().getValue() & 0xffffffff; + + // Handle BTF_INT_BITS in IntVal. + V = Die.findAttribute(dwarf::DW_AT_bit_size); + if (V.getType() == DIEValue::isInteger) + IntVal |= V.getDIEInteger().getValue() & 0xff; + else + IntVal |= (Size << 3) & 0xff; + + BTFType.Info = BTF_KIND_INT << 24; + BTFType.Size = Size; + this->IntVal = IntVal; +} + +void Die2BTFEntryInt::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + auto TypeV = Die.findAttribute(dwarf::DW_AT_type); + auto Str = NameV.getDIEString().getString(); + + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + + auto typeEntry = llvm::make_unique(Id, BTFType, IntVal); + Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry)); +} + +Die2BTFEntryEnum::Die2BTFEntryEnum(const DIE &Die) : Die2BTFEntry(Die) { + auto V = Die.findAttribute(dwarf::DW_AT_byte_size); + uint32_t Size = V.getDIEInteger().getValue() & 0xffffffff; + + uint32_t Vlen = 0; + for (auto &ChildDie : Die.children()) + if (ChildDie.getTag() == dwarf::DW_TAG_enumerator) + Vlen++; + + BTFType.Info = (BTF_KIND_ENUM << 24) | (Vlen & BTF_MAX_VLEN); + BTFType.Type = Size; +} + +void Die2BTFEntryEnum::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto TypeV = Die.findAttribute(dwarf::DW_AT_type); + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + + if (NameV.getType() != DIEValue::isNone) { + auto Str = NameV.getDIEString().getString(); + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + } else + BTFType.NameOff = 0; + + for (auto &ChildDie : Die.children()) { + struct BTFEnum BTFEnum; + auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name); + auto Str = ChildNameV.getDIEString().getString(); + + BTFEnum.NameOff = Dwarf2BTF.addBTFString(Str); + auto ChildValueV = ChildDie.findAttribute(dwarf::DW_AT_const_value); + BTFEnum.Val = (int32_t)(ChildValueV.getDIEInteger().getValue()); + + EnumValues.push_back(BTFEnum); + } + + auto typeEntry = llvm::make_unique(Id, BTFType, EnumValues); + Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry)); +} + +Die2BTFEntryArray::Die2BTFEntryArray(const DIE &Die) : Die2BTFEntry(Die) { + BTFType.Info = (BTF_KIND_ARRAY << 24); + BTFType.Size = 0; +} + +void Die2BTFEntryArray::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + + std::string Str; + if (NameV.getType() != DIEValue::isNone) + Str = NameV.getDIEString().getString(); + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + + auto &ArrayTypeDie = + Die.findAttribute(dwarf::DW_AT_type).getDIEEntry().getEntry(); + ArrayInfo.ElemType = Dwarf2BTF.getTypeIndex(ArrayTypeDie); + + // The number of elements should count all subranges. + unsigned Nelems = 1; + bool IsFirstSubrange = true; + for (auto &ChildDie : Die.children()) { + if (ChildDie.getTag() == dwarf::DW_TAG_subrange_type) { + if (IsFirstSubrange) { + auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_type); + auto &TypeDie = TypeV.getDIEEntry().getEntry(); + ArrayInfo.IndexType = Dwarf2BTF.getTypeIndex(TypeDie); + IsFirstSubrange = false; + } + auto CountV = ChildDie.findAttribute(dwarf::DW_AT_count); + if (CountV.getType() == DIEValue::isNone) { + // Handle array like a[] which essentially a pointer. + Nelems = 0; + break; + } + Nelems *= (uint32_t)(CountV.getDIEInteger().getValue()); + } + } + ArrayInfo.Nelems = Nelems; + + auto TypeEntry = llvm::make_unique(Id, BTFType, ArrayInfo); + Dwarf2BTF.addBTFTypeEntry(std::move(TypeEntry)); +} + +Die2BTFEntryStruct::Die2BTFEntryStruct(const DIE &Die) : Die2BTFEntry(Die) { + auto V = Die.findAttribute(dwarf::DW_AT_byte_size); + uint32_t Size = V.getDIEInteger().getValue() & 0xffffffff; + auto Kind = Die2BTFEntry::getDieKind(Die); + + int Vlen = 0; + for (auto &ChildDie : Die.children()) + if (ChildDie.getTag() == dwarf::DW_TAG_member) + Vlen++; + + BTFType.Size = Size; + BTFType.Info = (Kind << 24) | (Vlen & BTF_MAX_VLEN); +} + +void Die2BTFEntryStruct::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + + if (NameV.getType() != DIEValue::isNone) { + auto Str = NameV.getDIEString().getString(); + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + } else + BTFType.NameOff = 0; + + for (auto &ChildDie : Die.children()) { + if (ChildDie.getTag() != dwarf::DW_TAG_member) + continue; + + struct BTFMember BTFMember; + auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name); + + if (ChildNameV.getType() != DIEValue::isNone) { + auto Str = ChildNameV.getDIEString().getString(); + BTFMember.NameOff = Dwarf2BTF.addBTFString(Str); + } else + BTFMember.NameOff = 0; + + auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_type); + auto &TypeDie = TypeV.getDIEEntry().getEntry(); + BTFMember.Type = Dwarf2BTF.getTypeIndex(TypeDie); + + auto MemLocV = ChildDie.findAttribute(dwarf::DW_AT_data_member_location); + unsigned MemLoc = MemLocV.getDIEInteger().getValue() * 8; + + auto ByteSizeV = ChildDie.findAttribute(dwarf::DW_AT_byte_size); + if (ByteSizeV.getType() != DIEValue::isNone) { + unsigned ByteSize = ByteSizeV.getDIEInteger().getValue(); + auto BitOffsetV = ChildDie.findAttribute(dwarf::DW_AT_bit_offset); + unsigned BitOffset = BitOffsetV.getDIEInteger().getValue(); + auto BitSizeV = ChildDie.findAttribute(dwarf::DW_AT_bit_size); + unsigned BitSize = BitSizeV.getDIEInteger().getValue(); + if (Dwarf2BTF.isLittleEndian()) + MemLoc += ByteSize * 8 - BitSize - BitOffset; + else + MemLoc += BitOffset; + } + BTFMember.Offset = MemLoc; + + Members.push_back(BTFMember); + } + + auto typeEntry = llvm::make_unique(Id, BTFType, Members); + Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry)); +} + +Die2BTFEntryFunc::Die2BTFEntryFunc(const DIE &Die) : Die2BTFEntry(Die) { + auto Kind = Die2BTFEntry::getDieKind(Die); + + int Vlen = 0; + for (auto &ChildDie : Die.children()) + if (ChildDie.getTag() == dwarf::DW_TAG_formal_parameter) + Vlen++; + + IsFuncProto = Kind == BTF_KIND_FUNC_PROTO; + BTFType.Size = 0; + BTFType.Info = (Kind << 24) | (Vlen & BTF_MAX_VLEN); +} + +void Die2BTFEntryFunc::completeData(class Dwarf2BTF &Dwarf2BTF) { + auto NameV = Die.findAttribute(dwarf::DW_AT_name); + if (NameV.getType() == DIEValue::isNone) { + BTFType.NameOff = 0; + } else { + auto Str = NameV.getDIEString().getString(); + BTFType.NameOff = Dwarf2BTF.addBTFString(Str); + } + + auto RetTypeV = Die.findAttribute(dwarf::DW_AT_type); + if (RetTypeV.getType() != DIEValue::isNone) { + auto &TypeDie = RetTypeV.getDIEEntry().getEntry(); + BTFType.Type = Dwarf2BTF.getTypeIndex(TypeDie); + } else { + BTFType.Type = 0; + } + + for (auto &ChildDie : Die.children()) { + if (ChildDie.getTag() == dwarf::DW_TAG_formal_parameter) { + auto TypeV = ChildDie.findAttribute(dwarf::DW_AT_abstract_origin); + if (TypeV.getType() != DIEValue::isNone) { + auto &AbsOriginDie = TypeV.getDIEEntry().getEntry(); + assert(AbsOriginDie.getTag() == dwarf::DW_TAG_formal_parameter); + TypeV = AbsOriginDie.findAttribute(dwarf::DW_AT_type); + } else { + TypeV = ChildDie.findAttribute(dwarf::DW_AT_type); + } + auto &TypeDie = TypeV.getDIEEntry().getEntry(); + Parameters.push_back(Dwarf2BTF.getTypeIndex(TypeDie)); + } else if (ChildDie.getTag() == dwarf::DW_TAG_unspecified_parameters) { + Parameters.push_back(0); + } + } + + auto typeEntry = llvm::make_unique(Id, BTFType, Parameters); + Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry)); + + if (!IsFuncProto) { + auto LowPCV = Die.findAttribute(dwarf::DW_AT_low_pc); + if (LowPCV.getType() != DIEValue::isNone) { + const MCSymbol *Label = LowPCV.getDIELabel().getValue(); + BTFFuncInfo FuncInfo; + unsigned SecNameOff; + + FuncInfo.Label = Label; + FuncInfo.TypeId = Id; + if (Label->isInSection()) { + MCSection &Section = Label->getSection(); + MCSectionELF *SectionELF = dyn_cast(&Section); + assert(SectionELF); + SecNameOff = Dwarf2BTF.addBTFString(SectionELF->getSectionName()); + } else { + SecNameOff = Dwarf2BTF.addBTFString(".text"); + } + Dwarf2BTF.addBTFFuncInfo(SecNameOff, FuncInfo); + } + } +} + +Dwarf2BTF::Dwarf2BTF(MCContext &Context, bool IsLittleEndian) + : OuterCtx(Context), IsLE(IsLittleEndian) { + BTFContext = llvm::make_unique(); +} + +void Dwarf2BTF::addTypeEntry(const DIE &Die) { + for (auto &ChildDie : Die.children()) + addTypeEntry(ChildDie); + if (Die2BTFEntry::shouldSkipDie(Die)) + return; + auto Kind = Die2BTFEntry::getDieKind(Die); + if (Kind != BTF_KIND_UNKN) { + auto TypeEntry = Die2BTFEntry::dieToBTFTypeEntry(Die); + if (TypeEntry != nullptr) { + TypeEntry->setId(TypeEntries.size() + 1); + DieToIdMap[const_cast(&Die)] = TypeEntry->getId(); + TypeEntries.push_back(std::move(TypeEntry)); + } + } +} + +void Dwarf2BTF::addBTFTypeEntry(std::unique_ptr Entry) { + BTFContext->addTypeEntry(std::move(Entry)); +} + +void Dwarf2BTF::completeData() { + BTFContext->addString("\0"); + + for (auto &TypeEntry : TypeEntries) + TypeEntry->completeData(*this); +} + +void Dwarf2BTF::addDwarfCU(DwarfUnit *TheU) { + DIE &CuDie = TheU->getUnitDie(); + + assert((CuDie.getTag() == dwarf::DW_TAG_compile_unit) && + "Not a compile unit"); + addTypeEntry(CuDie); +} + +void Dwarf2BTF::finish() { + completeData(); + OuterCtx.setBTFContext(std::move(BTFContext)); +} + +} // namespace llvm Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -567,6 +567,9 @@ /// Emit the reference to the section. void emitSectionReference(const DwarfCompileUnit &CU); + /// Convert Dwarf data to BTF data. + void generateBTFfromDwarf(bool IsLittleEndian); + protected: /// Gather pre-function debug information. void beginFunctionImpl(const MachineFunction *MF) override; Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -971,6 +971,10 @@ // Emit the pubnames and pubtypes sections if requested. emitDebugPubSections(); + const Triple &TT = Asm->TM.getTargetTriple(); + if (TT.getArch() == Triple::bpfel || TT.getArch() == Triple::bpfeb) + generateBTFfromDwarf(TT.getArch() == Triple::bpfel); + // clean up. // FIXME: AbstractVariables.clear(); } @@ -2455,6 +2459,12 @@ return &SplitTypeUnitFileTable; } +void DwarfDebug::generateBTFfromDwarf(bool IsLittleEndian) { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + + Holder.generateBTFfromDwarf(IsLittleEndian); +} + uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) { MD5 Hash; Hash.update(Identifier); Index: lib/CodeGen/AsmPrinter/DwarfFile.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfFile.h +++ lib/CodeGen/AsmPrinter/DwarfFile.h @@ -114,6 +114,9 @@ void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr, bool UseRelativeOffsets = false); + /// Convert Dwarf data to BTF data. + void generateBTFfromDwarf(bool IsLittleEndian); + /// Returns the string pool. DwarfStringPool &getStringPool() { return StrPool; } Index: lib/CodeGen/AsmPrinter/DwarfFile.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "DwarfFile.h" +#include "Dwarf2BTF.h" #include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "DwarfUnit.h" @@ -15,6 +16,8 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/MC/MCBTFContext.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include #include @@ -88,6 +91,13 @@ StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets); } +void DwarfFile::generateBTFfromDwarf(bool IsLittleEndian) { + Dwarf2BTF Dwarf2BTF(Asm->OutContext, IsLittleEndian); + for (auto &TheU : CUs) + Dwarf2BTF.addDwarfCU(TheU.get()); + Dwarf2BTF.finish(); +} + bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { auto &ScopeVars = ScopeVariables[LS]; const DILocalVariable *DV = Var->getVariable(); Index: lib/MC/CMakeLists.txt =================================================================== --- lib/MC/CMakeLists.txt +++ lib/MC/CMakeLists.txt @@ -10,11 +10,13 @@ MCAsmMacro.cpp MCAsmStreamer.cpp MCAssembler.cpp + MCBTFContext.cpp MCCodeEmitter.cpp MCCodePadder.cpp MCCodeView.cpp MCContext.cpp MCDwarf.cpp + MCDwarf2BTF.cpp MCELFObjectTargetWriter.cpp MCELFStreamer.cpp MCExpr.cpp Index: lib/MC/MCBTFContext.cpp =================================================================== --- /dev/null +++ lib/MC/MCBTFContext.cpp @@ -0,0 +1,232 @@ +//===- lib/MC/MCBTFContext.cpp - Machine Code BTF Context -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCBTFContext.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" +#include +#include +#include + +using namespace llvm; + +#define DEBUG_TYPE "btf" + +static const char *const BTFKindStr[] = { +#define HANDLE_BTF_KIND(ID, NAME) #NAME, +#include "llvm/MC/MCBTF.def" +}; + +void MCBTFContext::addTypeEntry(std::unique_ptr Entry) { + TypeEntries.push_back(std::move(Entry)); +} + +void MCBTFContext::dump(raw_ostream &OS) { + OS << "Type Table:\n"; + for (auto &TypeEntry : TypeEntries) + TypeEntry->print(OS, *this); + + OS << "\nString Table:\n"; + StringTable.showTable(OS); + + OS << "\nFuncInfo Table:\n"; + for (auto &FuncSec : FuncInfoTable) { + OS << "SecNameOff=" << FuncSec.first << "\n"; + for (auto &FuncInfo : FuncSec.second) { + OS << "\tInsnOffset= TypeId=" << FuncInfo.TypeId << "\n"; + } + } + + OS << "\nLineInfo Table:\n"; + for (auto &LineSec : LineInfoTable) { + OS << "SecNameOff=" << LineSec.first << "\n"; + for (auto &LineInfo : LineSec.second) { + OS << "\tInsnOffset= FileNameOff=" << LineInfo.FileNameOff + << " LineOff=" << LineInfo.LineOff << " LineNum=" << LineInfo.LineNum + << " ColumnNum=" << LineInfo.ColumnNum << "\n"; + } + } +} + +void MCBTFContext::emitCommonHeader(MCObjectStreamer *MCOS) { + MCOS->EmitIntValue(BTF_MAGIC, 2); + MCOS->EmitIntValue(BTF_VERSION, 1); + MCOS->EmitIntValue(0, 1); +} + +void MCBTFContext::emitBTFSection(MCObjectStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + MCOS->SwitchSection(context.getObjectFileInfo()->getBTFSection()); + + // Emit header. + emitCommonHeader(MCOS); + MCOS->EmitIntValue(sizeof(struct BTFHeader), 4); + + uint32_t TypeLen = 0, StrLen; + for (auto &TypeEntry : TypeEntries) + TypeLen += TypeEntry->getSize(); + StrLen = StringTable.getSize(); + + MCOS->EmitIntValue(0, 4); + MCOS->EmitIntValue(TypeLen, 4); + MCOS->EmitIntValue(TypeLen, 4); + MCOS->EmitIntValue(StrLen, 4); + + // Emit type table. + for (auto &TypeEntry : TypeEntries) + TypeEntry->emitData(MCOS); + + // Emit string table. + for (auto &S : StringTable.getTable()) { + for (auto C : S) + MCOS->EmitIntValue(C, 1); + MCOS->EmitIntValue('\0', 1); + } +} + +void MCBTFContext::emitBTFExtSection(MCObjectStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + MCOS->SwitchSection(context.getObjectFileInfo()->getBTFExtSection()); + + // Emit header. + emitCommonHeader(MCOS); + MCOS->EmitIntValue(sizeof(struct BTFExtHeader), 4); + + uint32_t FuncLen = 0, LineLen = 0; + for (auto &FuncSec : FuncInfoTable) { + FuncLen += sizeof(struct BTFSecFuncInfo); + FuncLen += FuncSec.second.size() * sizeof(struct BPFFuncInfo); + } + for (auto &LineSec : LineInfoTable) { + LineLen += sizeof(struct BTFSecLineInfo); + LineLen += LineSec.second.size() * sizeof(struct BPFLineInfo); + } + + MCOS->EmitIntValue(0, 4); + MCOS->EmitIntValue(FuncLen, 4); + MCOS->EmitIntValue(FuncLen, 4); + MCOS->EmitIntValue(LineLen, 4); + + // Emit func_info table. + for (const auto &FuncSec : FuncInfoTable) { + MCOS->EmitIntValue(FuncSec.first, 4); + MCOS->EmitIntValue(FuncSec.second.size(), 4); + for (const auto &FuncInfo : FuncSec.second) { + MCOS->EmitBTFAdvanceLineAddr(FuncInfo.Label, 4); + MCOS->EmitIntValue(FuncInfo.TypeId, 4); + } + } + + // Emit line_info table. + for (const auto &LineSec : LineInfoTable) { + MCOS->EmitIntValue(LineSec.first, 4); + MCOS->EmitIntValue(LineSec.second.size(), 4); + for (const auto &LineInfo : LineSec.second) { + MCOS->EmitBTFAdvanceLineAddr(LineInfo.Label, 4); + MCOS->EmitIntValue(LineInfo.FileNameOff, 4); + MCOS->EmitIntValue(LineInfo.LineOff, 4); + MCOS->EmitIntValue(LineInfo.LineNum << 10 | LineInfo.ColumnNum, 4); + } + } +} + +void MCBTFContext::emit(MCObjectStreamer *MCOS) { + LLVM_DEBUG(dump(dbgs())); + emitBTFSection(MCOS); + emitBTFExtSection(MCOS); +} + +void BTFTypeEntry::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + OS << "[" << Id << "] " << BTFKindStr[getKind()] + << " NameOff=" << BTFType.NameOff + << " Info=" << format("0x%08lx", BTFType.Info) + << " Size/Type=" << BTFType.Size << "\n"; +} + +BTFTypeEntry::~BTFTypeEntry() {} + +void BTFTypeEntry::emitData(MCObjectStreamer *MCOS) { + MCOS->EmitIntValue(BTFType.NameOff, 4); + MCOS->EmitIntValue(BTFType.Info, 4); + MCOS->EmitIntValue(BTFType.Size, 4); +} + +void BTFTypeEntryInt::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + BTFTypeEntry::print(OS, MCBTFContext); + OS << "\tDesc=" << format("0x%08lx", IntVal) << "\n"; +} + +void BTFTypeEntryInt::emitData(MCObjectStreamer *MCOS) { + BTFTypeEntry::emitData(MCOS); + MCOS->EmitIntValue(IntVal, 4); +} + +void BTFTypeEntryEnum::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + BTFTypeEntry::print(OS, MCBTFContext); + for (size_t i = 0; i < getVlen(); i++) { + auto &EnumValue = EnumValues[i]; + OS << "\tNameOff=" << EnumValue.NameOff << " Value=" << EnumValue.Val + << "\n"; + } +} + +void BTFTypeEntryEnum::emitData(MCObjectStreamer *MCOS) { + BTFTypeEntry::emitData(MCOS); + for (auto &EnumValue : EnumValues) { + MCOS->EmitIntValue(EnumValue.NameOff, 4); + MCOS->EmitIntValue(EnumValue.Val, 4); + } +} + +void BTFTypeEntryArray::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + BTFTypeEntry::print(OS, MCBTFContext); + OS << "\tElemType=" << format("0x%08lx", ArrayInfo.ElemType) + << " IndexType=" << format("0x%08lx", ArrayInfo.IndexType) + << " Nelems=" << ArrayInfo.Nelems << "\n"; +} + +void BTFTypeEntryArray::emitData(MCObjectStreamer *MCOS) { + BTFTypeEntry::emitData(MCOS); + MCOS->EmitIntValue(ArrayInfo.ElemType, 4); + MCOS->EmitIntValue(ArrayInfo.IndexType, 4); + MCOS->EmitIntValue(ArrayInfo.Nelems, 4); +} + +void BTFTypeEntryStruct::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + BTFTypeEntry::print(OS, MCBTFContext); + for (size_t i = 0; i < getVlen(); i++) { + auto &Member = Members[i]; + OS << "\tNameOff=" << Member.NameOff << " Type=" << Member.Type + << " BitOffset=" << Member.Offset << "\n"; + } +} + +void BTFTypeEntryStruct::emitData(MCObjectStreamer *MCOS) { + BTFTypeEntry::emitData(MCOS); + for (auto &Member : Members) { + MCOS->EmitIntValue(Member.NameOff, 4); + MCOS->EmitIntValue(Member.Type, 4); + MCOS->EmitIntValue(Member.Offset, 4); + } +} + +void BTFTypeEntryFunc::print(raw_ostream &OS, MCBTFContext &MCBTFContext) { + BTFTypeEntry::print(OS, MCBTFContext); + for (size_t i = 0; i < getVlen(); i++) { + auto Parameter = Parameters[i]; + OS << "\tParamType=" << Parameter << "\n"; + } +} + +void BTFTypeEntryFunc::emitData(MCObjectStreamer *MCOS) { + BTFTypeEntry::emitData(MCOS); + for (auto &Parameter : Parameters) + MCOS->EmitIntValue(Parameter, 4); +} Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -17,6 +17,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCBTFContext.h" #include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" @@ -60,7 +61,7 @@ : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi), Symbols(Allocator), UsedNames(Allocator), CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), - AutoReset(DoAutoReset) { + AutoReset(DoAutoReset), BTFCtx(nullptr) { SecureLogFile = AsSecureLogFileName; if (SrcMgr && SrcMgr->getNumBuffers()) @@ -114,6 +115,14 @@ GenDwarfFileNumber = 0; HadError = false; + BTFCtx.reset(); +} + +//===----------------------------------------------------------------------===// +// BTFCtx Manipulation +//===----------------------------------------------------------------------===// +void MCContext::setBTFContext(std::unique_ptr Ctx) { + BTFCtx = std::move(Ctx); } //===----------------------------------------------------------------------===// Index: lib/MC/MCDwarf2BTF.h =================================================================== --- /dev/null +++ lib/MC/MCDwarf2BTF.h @@ -0,0 +1,32 @@ +//===- MCDwarf2BTF.h ------------------------------------------ *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_MC_MCDWARF2BTF_H +#define LLVM_LIB_MC_MCDWARF2BTF_H + +#include "llvm/MC/MCDwarf.h" + +namespace llvm { + +using FileContent = std::pair>; + +/// Converting Dwarf debug_line to BTF line_info +class MCDwarf2BTF { +public: + static void addFiles(MCObjectStreamer *MCOS, std::string &FileName, + std::vector &Files, + Optional Source); + static void + addLines(MCObjectStreamer *MCOS, StringRef &SectionName, + std::vector &Files, + const MCLineSection::MCDwarfLineEntryCollection &LineEntries); + static void addDwarfLineInfo(MCObjectStreamer *MCOS); +}; + +} // namespace llvm +#endif Index: lib/MC/MCDwarf2BTF.cpp =================================================================== --- /dev/null +++ lib/MC/MCDwarf2BTF.cpp @@ -0,0 +1,110 @@ +//===- MCDwarf2BTF.cpp ---------------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCDwarf2BTF.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCBTFContext.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" +#include +#include + +using namespace llvm; + +void MCDwarf2BTF::addFiles(MCObjectStreamer *MCOS, std::string &FileName, + std::vector &Files, + Optional Source) { + std::vector Content; + std::string Line; + Content.push_back(Line); // Line 0 for empty string + + if (Source) { + std::istringstream InputString(Source.getValue()); + while (std::getline(InputString, Line)) + Content.push_back(Line); + } else { + std::ifstream InputFile(FileName); + while (std::getline(InputFile, Line)) + Content.push_back(Line); + } + + Files.push_back(FileContent(FileName, Content)); +} + +void MCDwarf2BTF::addLines( + MCObjectStreamer *MCOS, StringRef &SectionName, + std::vector &Files, + const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { + MCContext &Context = MCOS->getContext(); + auto &BTFCxt = Context.getBTFContext(); + + unsigned SecNameOff = BTFCxt->addString(SectionName); + for (const MCDwarfLineEntry &LineEntry : LineEntries) { + BTFLineInfo LineInfo; + unsigned FileNum = LineEntry.getFileNum(); + unsigned Line = LineEntry.getLine(); + + LineInfo.Label = LineEntry.getLabel(); + if (FileNum < Files.size()) { + LineInfo.FileNameOff = BTFCxt->addString(Files[FileNum].first); + if (Line < Files[FileNum].second.size()) + LineInfo.LineOff = BTFCxt->addString(Files[FileNum].second[Line]); + else + LineInfo.LineOff = 0; + } else { + LineInfo.FileNameOff = 0; + LineInfo.LineOff = 0; + } + LineInfo.LineNum = Line; + LineInfo.ColumnNum = LineEntry.getColumn(); + BTFCxt->addLineInfo(SecNameOff, LineInfo); + } +} + +void MCDwarf2BTF::addDwarfLineInfo(MCObjectStreamer *MCOS) { + MCContext &Context = MCOS->getContext(); + + auto &LineTables = Context.getMCDwarfLineTables(); + if (LineTables.empty()) + return; + + for (const auto &CUIDTablePair : LineTables) { + std::vector Dirs; + std::vector Files; + + for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs()) + Dirs.push_back(Dir); + for (auto &File : CUIDTablePair.second.getMCDwarfFiles()) { + std::string FileName; + if (File.DirIndex == 0) + FileName = File.Name; + else + FileName = Dirs[File.DirIndex - 1] + "/" + File.Name; + MCDwarf2BTF::addFiles(MCOS, FileName, Files, File.Source); + } + for (const auto &LineSec : + CUIDTablePair.second.getMCLineSections().getMCLineEntries()) { + MCSection *Section = LineSec.first; + const MCLineSection::MCDwarfLineEntryCollection &LineEntries = + LineSec.second; + + StringRef SectionName; + if (MCSectionELF *SectionELF = dyn_cast(Section)) + SectionName = SectionELF->getSectionName(); + else + return; + MCDwarf2BTF::addLines(MCOS, SectionName, Files, LineEntries); + } + } +} Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -468,6 +468,9 @@ Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags); StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0); + + BTFSection = Ctx->getELFSection(".BTF", ELF::SHT_PROGBITS, 0); + BTFExtSection = Ctx->getELFSection(".BTF.ext", ELF::SHT_PROGBITS, 0); } void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { Index: lib/MC/MCObjectStreamer.cpp =================================================================== --- lib/MC/MCObjectStreamer.cpp +++ lib/MC/MCObjectStreamer.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCBTFContext.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" @@ -21,6 +22,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SourceMgr.h" +#include "MCDwarf2BTF.h" using namespace llvm; MCObjectStreamer::MCObjectStreamer(MCContext &Context, @@ -439,6 +441,31 @@ insert(new MCDwarfCallFrameFragment(*AddrDelta)); } +void MCObjectStreamer::EmitBTFAdvanceLineAddr(const MCSymbol *Label, + unsigned Size) { + const MCExpr *Value = MCSymbolRefExpr::create(Label, getContext()); + MCDataFragment *DF = getOrCreateDataFragment(); + + // Avoid fixups when possible. + int64_t AbsValue; + SMLoc Loc; + + if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) { + if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) { + getContext().reportError( + Loc, "value evaluated as " + Twine(AbsValue) + " is out of range."); + return; + } + EmitIntValue(AbsValue, Size); + return; + } + + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, + MCFixup::getKindForSize(Size, false), Loc)); + DF->getContents().resize(DF->getContents().size() + Size, 0); +} + void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, @@ -688,6 +715,13 @@ // Dump out the dwarf file & directory tables and line tables. MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams()); + auto &BTFCtx = getContext().getBTFContext(); + if (BTFCtx) { + MCDwarf2BTF::addDwarfLineInfo(this); + BTFCtx->emit(this); + BTFCtx.reset(); + } + flushPendingLabels(); getAssembler().Finish(); } Index: test/MC/BPF/btf-dwarf5-source.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-dwarf5-source.ll @@ -0,0 +1,55 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Test source code can be retrieved from DIFile.Source +; Source compiled with: +; clang -target bpf -O2 -g -gdwarf-5 -gembed-source -emit-llvm -S t.c +; Source code: +; int f() { return 0; } + +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 1c000000 +; CHECK-EL: 0x00000010 1c000000 27000000 01000000 0000000c +; CHECK-EL: 0x00000020 02000000 09000000 00000001 04000000 +; CHECK-EL: 0x00000030 20000001 0066002e 74657874 00696e74 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000001c +; CHECK-EB: 0x00000010 0000001c 00000027 00000001 0c000000 +; CHECK-EB: 0x00000020 00000002 00000009 01000000 00000004 +; CHECK-EB: 0x00000030 01000020 0066002e 74657874 00696e74 +; CHECK: 0x00000040 00742e63 00696e74 20662829 207b2072 +; CHECK: 0x00000050 65747572 6e20303b 207d00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 28000000 03000000 01000000 +; CHECK-EL: 0x00000020 00000000 01000000 03000000 02000000 +; CHECK-EL: 0x00000030 00000000 0d000000 11000000 00040000 +; CHECK-EL: 0x00000040 00000000 0d000000 11000000 0b040000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000028 00000003 00000001 +; CHECK-EB: 0x00000020 00000000 00000001 00000003 00000002 +; CHECK-EB: 0x00000030 00000000 0000000d 00000011 00000400 +; CHECK-EB: 0x00000040 00000000 0000000d 00000011 0000040b +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @f() local_unnamed_addr #0 !dbg !7 { +entry: + ret i32 0, !dbg !11 +} + +attributes #0 = { norecurse nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344750) (llvm/trunk 344756)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "t.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "2f19608caecd442f6d54defa0da35971", source: "int f() { return 0; }\0A") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344750) (llvm/trunk 344756)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagAllCallsDescribed, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocation(line: 1, column: 11, scope: !7) Index: test/MC/BPF/btf-ext-1.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-ext-1.ll @@ -0,0 +1,54 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Test .BTF.ext section generation. +; Source code: +; int f() { return 0; } + +; .BTF: two types: func, int +; .BTF.ext: func_info: one sec with one func +; line_info: one sec with two entries +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 1c000000 +; CHECK-EL: 0x00000010 1c000000 13000000 01000000 0000000c +; CHECK-EL: 0x00000020 02000000 09000000 00000001 04000000 +; CHECK-EL: 0x00000030 20000001 0066002e 74657874 00696e74 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000001c +; CHECK-EB: 0x00000010 0000001c 00000013 00000001 0c000000 +; CHECK-EB: 0x00000020 00000002 00000009 01000000 00000004 +; CHECK-EB: 0x00000030 01000020 0066002e 74657874 00696e74 +; CHECK: 0x00000040 00737263 2e6300 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 28000000 03000000 01000000 +; CHECK-EL: 0x00000020 00000000 01000000 03000000 02000000 +; CHECK-EL: 0x00000030 00000000 0d000000 00000000 00040000 +; CHECK-EL: 0x00000040 00000000 0d000000 00000000 0b040000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000028 00000003 00000001 +; CHECK-EB: 0x00000020 00000000 00000001 00000003 00000002 +; CHECK-EB: 0x00000030 00000000 0000000d 00000000 00000400 +; CHECK-EB: 0x00000040 00000000 0000000d 00000000 0000040b +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @f() local_unnamed_addr #0 !dbg !7 { + ret i32 0, !dbg !11 +} + +attributes #0 = { norecurse nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "src.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocation(line: 1, column: 11, scope: !7) Index: test/MC/BPF/btf-ext-2.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-ext-2.ll @@ -0,0 +1,71 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Test .BTF.ext section generation. +; Source code: +; __attribute__((section("SecA"))) int f() { return 0; } +; __attribute__((section("SecB"))) int g() { return 0; } + +; .BTF: three types: func f(), func g(), int +; .BTF.ext: func_info: two sections, each with one entry +; line_info: two sections, each with two entries +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 28000000 +; CHECK-EL: 0x00000010 28000000 19000000 01000000 0000000c +; CHECK-EL: 0x00000020 03000000 08000000 0000000c 03000000 +; CHECK-EL: 0x00000030 0f000000 00000001 04000000 20000001 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000028 +; CHECK-EB: 0x00000010 00000028 00000019 00000001 0c000000 +; CHECK-EB: 0x00000020 00000003 00000008 0c000000 00000003 +; CHECK-EB: 0x00000030 0000000f 01000000 00000004 01000020 +; CHECK: 0x00000040 00660053 65634100 67005365 63420069 +; CHECK: 0x00000050 6e740073 72632e63 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 20000000 +; CHECK-EL: 0x00000010 20000000 50000000 03000000 01000000 +; CHECK-EL: 0x00000020 00000000 01000000 0a000000 01000000 +; CHECK-EL: 0x00000030 00000000 02000000 03000000 02000000 +; CHECK-EL: 0x00000040 00000000 13000000 00000000 00040000 +; CHECK-EL: 0x00000050 00000000 13000000 00000000 2c040000 +; CHECK-EL: 0x00000060 0a000000 02000000 00000000 13000000 +; CHECK-EL: 0x00000070 00000000 00080000 00000000 13000000 +; CHECK-EL: 0x00000080 00000000 2c080000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000020 +; CHECK-EB: 0x00000010 00000020 00000050 00000003 00000001 +; CHECK-EB: 0x00000020 00000000 00000001 0000000a 00000001 +; CHECK-EB: 0x00000030 00000000 00000002 00000003 00000002 +; CHECK-EB: 0x00000040 00000000 00000013 00000000 00000400 +; CHECK-EB: 0x00000050 00000000 00000013 00000000 0000042c +; CHECK-EB: 0x00000060 0000000a 00000002 00000000 00000013 +; CHECK-EB: 0x00000070 00000000 00000800 00000000 00000013 +; CHECK-EB: 0x00000080 00000000 0000082c +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @f() local_unnamed_addr #0 section "SecA" !dbg !7 { + ret i32 0, !dbg !11 +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @g() local_unnamed_addr #0 section "SecB" !dbg !12 { + ret i32 0, !dbg !13 +} + +attributes #0 = { norecurse nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "src.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} +!7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{!10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DILocation(line: 1, column: 44, scope: !7) +!12 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, retainedNodes: !2) +!13 = !DILocation(line: 2, column: 44, scope: !12) Index: test/MC/BPF/btf-type-array-1.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-array-1.ll @@ -0,0 +1,45 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; char a[64]; + +; .BTF: three types: array, array element, array index +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 38000000 +; CHECK-EL: 0x00000010 38000000 1a000000 00000000 00000003 +; CHECK-EL: 0x00000020 00000000 02000000 03000000 40000000 +; CHECK-EL: 0x00000030 01000000 00000001 01000000 08000002 +; CHECK-EL: 0x00000040 06000000 00000001 08000000 40000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000038 +; CHECK-EB: 0x00000010 00000038 0000001a 00000000 03000000 +; CHECK-EB: 0x00000020 00000000 00000002 00000003 00000040 +; CHECK-EB: 0x00000030 00000001 01000000 00000001 02000008 +; CHECK-EB: 0x00000040 00000006 01000000 00000008 00000040 +; CHECK: 0x00000050 00636861 72005f5f 41525241 595f5349 +; CHECK: 0x00000060 5a455f54 5950455f 5f00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global [64 x i8] zeroinitializer, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 512, elements: !8) +!7 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!8 = !{!9} +!9 = !DISubrange(count: 64) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-array-2.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-array-2.ll @@ -0,0 +1,45 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; char a[8][8]; + +; .BTF: three types: array, array element, array index +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 38000000 +; CHECK-EL: 0x00000010 38000000 1a000000 00000000 00000003 +; CHECK-EL: 0x00000020 00000000 02000000 03000000 40000000 +; CHECK-EL: 0x00000030 01000000 00000001 01000000 08000002 +; CHECK-EL: 0x00000040 06000000 00000001 08000000 40000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000038 +; CHECK-EB: 0x00000010 00000038 0000001a 00000000 03000000 +; CHECK-EB: 0x00000020 00000000 00000002 00000003 00000040 +; CHECK-EB: 0x00000030 00000001 01000000 00000001 02000008 +; CHECK-EB: 0x00000040 00000006 01000000 00000008 00000040 +; CHECK: 0x00000050 00636861 72005f5f 41525241 595f5349 +; CHECK: 0x00000060 5a455f54 5950455f 5f00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global [8 x [8 x i8]] zeroinitializer, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 512, elements: !8) +!7 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!8 = !{!9, !9} +!9 = !DISubrange(count: 8) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-char.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-char.ll @@ -0,0 +1,36 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; char a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 06000000 01000000 00000001 +; CHECK-EL: 0x00000020 01000000 08000002 00636861 7200 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000006 00000001 01000000 +; CHECK-EB: 0x00000020 00000001 02000008 00636861 7200 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i8 0, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-const.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-const.ll @@ -0,0 +1,41 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; const int *a; + +; .BTF: three types: pointer, const, int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 28000000 +; CHECK-EL: 0x00000010 28000000 05000000 00000000 00000002 +; CHECK-EL: 0x00000020 02000000 00000000 0000000a 03000000 +; CHECK-EL: 0x00000030 01000000 00000001 04000000 20000001 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000028 +; CHECK-EB: 0x00000010 00000028 00000005 00000000 02000000 +; CHECK-EB: 0x00000020 00000002 00000000 0a000000 00000003 +; CHECK-EB: 0x00000030 00000001 01000000 00000004 01000020 +; CHECK: 0x00000040 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-enum.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-enum.ll @@ -0,0 +1,45 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; enum { A, B } a; + +; .BTF: two types: enum, unsigned int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 2c000000 +; CHECK-EL: 0x00000010 2c000000 12000000 00000000 02000006 +; CHECK-EL: 0x00000020 04000000 01000000 00000000 03000000 +; CHECK-EL: 0x00000030 01000000 05000000 00000001 04000000 +; CHECK-EL: 0x00000040 20000000 00410042 00756e73 69676e65 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000002c +; CHECK-EB: 0x00000010 0000002c 00000012 00000000 06000002 +; CHECK-EB: 0x00000020 00000004 00000001 00000000 00000003 +; CHECK-EB: 0x00000030 00000001 00000005 01000000 00000004 +; CHECK-EB: 0x00000040 00000020 00410042 00756e73 69676e65 +; CHECK: 0x00000050 6420696e 7400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !3, line: 1, baseType: !6, size: 32, elements: !7) +!6 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!7 = !{!8, !9} +!8 = !DIEnumerator(name: "A", value: 0, isUnsigned: true) +!9 = !DIEnumerator(name: "B", value: 1, isUnsigned: true) +!10 = !{!0} +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-forward.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-forward.ll @@ -0,0 +1,40 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; struct t; struct t *a; + +; .BTF: two types: ptr, fwd +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 18000000 +; CHECK-EL: 0x00000010 18000000 03000000 00000000 00000002 +; CHECK-EL: 0x00000020 02000000 01000000 00000007 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000018 +; CHECK-EB: 0x00000010 00000018 00000003 00000000 02000000 +; CHECK-EB: 0x00000020 00000002 00000001 07000000 00000000 +; CHECK: 0x00000030 007400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +%struct.t = type opaque + +@a = common dso_local local_unnamed_addr global %struct.t* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, flags: DIFlagFwdDecl) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-func-proto.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-func-proto.ll @@ -0,0 +1,43 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; void (*f)(int); + +; .BTF: three types: ptr, func_proto, int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 2c000000 +; CHECK-EL: 0x00000010 2c000000 05000000 00000000 00000002 +; CHECK-EL: 0x00000020 02000000 00000000 0100000d 00000000 +; CHECK-EL: 0x00000030 03000000 01000000 00000001 04000000 +; CHECK-EL: 0x00000040 20000001 00696e74 00 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000002c +; CHECK-EB: 0x00000010 0000002c 00000005 00000000 02000000 +; CHECK-EB: 0x00000020 00000002 00000000 0d000001 00000000 +; CHECK-EB: 0x00000030 00000003 00000001 01000000 00000004 +; CHECK-EB: 0x00000040 01000020 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@f = common dso_local local_unnamed_addr global void (i32)* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "f", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DISubroutineType(types: !8) +!8 = !{null, !9} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{i32 2, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-int.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-int.ll @@ -0,0 +1,36 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; int a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 05000000 01000000 00000001 +; CHECK-EL: 0x00000020 04000000 20000001 00696e74 00 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000005 00000001 01000000 +; CHECK-EB: 0x00000020 00000004 01000020 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-llong.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-llong.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; long long a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 0f000000 01000000 00000001 +; CHECK-EL: 0x00000020 08000000 40000001 006c6f6e 67206c6f +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 0000000f 00000001 01000000 +; CHECK-EB: 0x00000020 00000008 01000040 006c6f6e 67206c6f +; CHECK: 0x00000030 6e672069 6e7400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i64 0, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-ptr-int.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-ptr-int.ll @@ -0,0 +1,39 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; int *a; + +; .BTF: two types: ptr, int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 1c000000 +; CHECK-EL: 0x00000010 1c000000 05000000 00000000 00000002 +; CHECK-EL: 0x00000020 02000000 01000000 00000001 04000000 +; CHECK-EL: 0x00000030 20000001 00696e74 00 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000001c +; CHECK-EB: 0x00000010 0000001c 00000005 00000000 02000000 +; CHECK-EB: 0x00000020 00000002 00000001 01000000 00000004 +; CHECK-EB: 0x00000030 01000020 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-ptr-void.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-ptr-void.ll @@ -0,0 +1,35 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; void *a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 0c000000 +; CHECK-EL: 0x00000010 0c000000 01000000 00000000 00000002 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000000c +; CHECK-EB: 0x00000010 0000000c 00000001 00000000 02000000 +; CHECK: 0x00000020 00000000 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i8* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-short.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-short.ll @@ -0,0 +1,36 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; short a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 07000000 01000000 00000001 +; CHECK-EL: 0x00000020 02000000 10000001 0073686f 727400 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000007 00000001 01000000 +; CHECK-EB: 0x00000020 00000002 01000010 0073686f 727400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i16 0, align 2, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-struct-1.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-struct-1.ll @@ -0,0 +1,50 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; struct t { int m1; char m2; } a; + +; .BTF: three types: struct t, int, char +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 44000000 +; CHECK-EL: 0x00000010 44000000 12000000 01000000 02000004 +; CHECK-EL: 0x00000020 08000000 03000000 02000000 00000000 +; CHECK-EL: 0x00000030 06000000 03000000 20000000 09000000 +; CHECK-EL: 0x00000040 00000001 04000000 20000001 0d000000 +; CHECK-EL: 0x00000050 00000001 01000000 08000002 0074006d +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000044 +; CHECK-EB: 0x00000010 00000044 00000012 00000001 04000002 +; CHECK-EB: 0x00000020 00000008 00000003 00000002 00000000 +; CHECK-EB: 0x00000030 00000006 00000003 00000020 00000009 +; CHECK-EB: 0x00000040 01000000 00000004 01000020 0000000d +; CHECK-EB: 0x00000050 01000000 00000001 02000008 0074006d +; CHECK: 0x00000060 31006d32 00696e74 00636861 7200 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +%struct.t = type { i32, i8 } + +@a = common dso_local local_unnamed_addr global %struct.t zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, size: 64, elements: !7) +!7 = !{!8, !10} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !6, file: !3, line: 1, baseType: !9, size: 32) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "m2", scope: !6, file: !3, line: 1, baseType: !11, size: 8, offset: 32) +!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-struct-2.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-struct-2.ll @@ -0,0 +1,50 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; struct t { int m0; int m1:2; int m2:2; } a; + +; .BTF: two types: struct t, int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 40000000 +; CHECK-EL: 0x00000010 40000000 10000000 01000000 03000004 +; CHECK-EL: 0x00000020 08000000 03000000 02000000 00000000 +; CHECK-EL: 0x00000030 06000000 02000000 20000000 09000000 +; CHECK-EL: 0x00000040 02000000 22000000 0c000000 00000001 +; CHECK-EL: 0x00000050 04000000 20000001 0074006d 30006d31 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000040 +; CHECK-EB: 0x00000010 00000040 00000010 00000001 04000003 +; CHECK-EB: 0x00000020 00000008 00000003 00000002 00000000 +; CHECK-EB: 0x00000030 00000006 00000002 00000020 00000009 +; CHECK-EB: 0x00000040 00000002 00000022 0000000c 01000000 +; CHECK-EB: 0x00000050 00000004 01000020 0074006d 30006d31 +; CHECK: 0x00000060 006d3200 696e7400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +%struct.t = type { i32, i8 } + +@a = common dso_local local_unnamed_addr global %struct.t zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, size: 64, elements: !7) +!7 = !{!8, !10, !11} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m0", scope: !6, file: !3, line: 1, baseType: !9, size: 32) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !6, file: !3, line: 1, baseType: !9, size: 2, offset: 32, flags: DIFlagBitField, extraData: i64 32) +!11 = !DIDerivedType(tag: DW_TAG_member, name: "m2", scope: !6, file: !3, line: 1, baseType: !9, size: 2, offset: 34, flags: DIFlagBitField, extraData: i64 32) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-typedef.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-typedef.ll @@ -0,0 +1,39 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; typedef int __int; __int a; + +; .BTF: two types: typedef, int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 1c000000 +; CHECK-EL: 0x00000010 1c000000 05000000 00000000 00000008 +; CHECK-EL: 0x00000020 02000000 01000000 00000001 04000000 +; CHECK-EL: 0x00000030 20000001 00696e74 00 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000001c +; CHECK-EB: 0x00000010 0000001c 00000005 00000000 08000000 +; CHECK-EB: 0x00000020 00000002 00000001 01000000 00000004 +; CHECK-EB: 0x00000030 01000020 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !3, line: 1, baseType: !7) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-uchar.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-uchar.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; unsigned char a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 0f000000 01000000 00000001 +; CHECK-EL: 0x00000020 01000000 08000002 00756e73 69676e65 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 0000000f 00000001 01000000 +; CHECK-EB: 0x00000020 00000001 02000008 00756e73 69676e65 +; CHECK: 0x00000030 64206368 617200 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i8 0, align 1, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-uint.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-uint.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; unsigned int a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 0e000000 01000000 00000001 +; CHECK-EL: 0x00000020 04000000 20000000 00756e73 69676e65 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 0000000e 00000001 01000000 +; CHECK-EB: 0x00000020 00000004 00000020 00756e73 69676e65 +; CHECK: 0x00000030 6420696e 7400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-ullong.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-ullong.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; unsigned long long a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 18000000 01000000 00000001 +; CHECK-EL: 0x00000020 08000000 40000000 006c6f6e 67206c6f +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000018 00000001 01000000 +; CHECK-EB: 0x00000020 00000008 00000040 006c6f6e 67206c6f +; CHECK: 0x00000030 6e672075 6e736967 6e656420 696e7400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i64 0, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-union.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-union.ll @@ -0,0 +1,50 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; union t { int m1; char m2; } a; + +; .BTF: three types: union t, int, char +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 44000000 +; CHECK-EL: 0x00000010 44000000 12000000 01000000 02000005 +; CHECK-EL: 0x00000020 04000000 03000000 02000000 00000000 +; CHECK-EL: 0x00000030 06000000 03000000 00000000 09000000 +; CHECK-EL: 0x00000040 00000001 04000000 20000001 0d000000 +; CHECK-EL: 0x00000050 00000001 01000000 08000002 0074006d +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000044 +; CHECK-EB: 0x00000010 00000044 00000012 00000001 05000002 +; CHECK-EB: 0x00000020 00000004 00000003 00000002 00000000 +; CHECK-EB: 0x00000030 00000006 00000003 00000000 00000009 +; CHECK-EB: 0x00000040 01000000 00000004 01000020 0000000d +; CHECK-EB: 0x00000050 01000000 00000001 02000008 0074006d +; CHECK: 0x00000060 31006d32 00696e74 00636861 7200 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +%union.t = type { i32 } + +@a = common dso_local local_unnamed_addr global %union.t zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "t", file: !3, line: 1, size: 32, elements: !7) +!7 = !{!8, !10} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "m1", scope: !6, file: !3, line: 1, baseType: !9, size: 32) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DIDerivedType(tag: DW_TAG_member, name: "m2", scope: !6, file: !3, line: 1, baseType: !11, size: 8) +!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-ushort.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-ushort.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; unsigned short a; + +; .BTF: one type +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 10000000 +; CHECK-EL: 0x00000010 10000000 10000000 01000000 00000001 +; CHECK-EL: 0x00000020 02000000 10000000 00756e73 69676e65 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000010 +; CHECK-EB: 0x00000010 00000010 00000010 00000001 01000000 +; CHECK-EB: 0x00000020 00000002 00000010 00756e73 69676e65 +; CHECK: 0x00000030 64207368 6f727400 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i16 0, align 2, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9} +!llvm.ident = !{!10} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned) +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"} Index: test/MC/BPF/btf-type-volatile.ll =================================================================== --- /dev/null +++ test/MC/BPF/btf-type-volatile.ll @@ -0,0 +1,40 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EL %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -x ".BTF" -x ".BTF.ext" | FileCheck -check-prefixes=CHECK,CHECK-EB %s + +; Source code: +; volatile int a; + +; .BTF: two types: volatile, int +; strings: int +; .BTF.ext: empty (only header) +; CHECK: '.BTF' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 1c000000 +; CHECK-EL: 0x00000010 1c000000 05000000 00000000 00000009 +; CHECK-EL: 0x00000020 02000000 01000000 00000001 04000000 +; CHECK-EL: 0x00000030 20000001 00696e74 00 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 0000001c +; CHECK-EB: 0x00000010 0000001c 00000005 00000000 09000000 +; CHECK-EB: 0x00000020 00000002 00000001 01000000 00000004 +; CHECK-EB: 0x00000030 01000020 00696e74 00 +; CHECK: '.BTF.ext' +; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 00000000 +; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000000 +; CHECK: 0x00000010 00000000 00000000 +@a = common dso_local local_unnamed_addr global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!8, !9, !10} +!llvm.ident = !{!11} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None) +!3 = !DIFile(filename: "src.c", directory: "/tmp") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !{i32 1, !"wchar_size", i32 4} +!11 = !{!"clang version 8.0.0 (trunk 344388) (llvm/trunk 344405)"}