summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp501
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.h134
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp10
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp10
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfFile.h3
-rw-r--r--llvm/lib/MC/CMakeLists.txt2
-rw-r--r--llvm/lib/MC/MCBTFContext.cpp235
-rw-r--r--llvm/lib/MC/MCContext.cpp11
-rw-r--r--llvm/lib/MC/MCDwarf2BTF.cpp99
-rw-r--r--llvm/lib/MC/MCDwarf2BTF.h29
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp3
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp34
14 files changed, 1074 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 6cba4a0d4b8..14c895a9c82 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -17,6 +17,7 @@ add_llvm_library(LLVMAsmPrinter
DwarfFile.cpp
DwarfStringPool.cpp
DwarfUnit.cpp
+ Dwarf2BTF.cpp
EHStreamer.cpp
ErlangGCPrinter.cpp
OcamlGCPrinter.cpp
diff --git a/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp b/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp
new file mode 100644
index 00000000000..20eab4d1fb8
--- /dev/null
+++ b/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.cpp
@@ -0,0 +1,501 @@
+//===- 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 "DwarfUnit.h"
+#include "Dwarf2BTF.h"
+#include "llvm/MC/MCBTFContext.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+
+namespace llvm {
+
+unsigned char 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> Die2BTFEntry::dieToBTFTypeEntry(const DIE &Die) {
+ unsigned char Kind = getDieKind(Die);
+
+ switch (Kind) {
+ case BTF_KIND_INT:
+ return make_unique<Die2BTFEntryInt>(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 make_unique<Die2BTFEntry>(Die);
+ case BTF_KIND_ARRAY:
+ return make_unique<Die2BTFEntryArray>(Die);
+ case BTF_KIND_STRUCT:
+ case BTF_KIND_UNION:
+ return make_unique<Die2BTFEntryStruct>(Die);
+ case BTF_KIND_ENUM:
+ return make_unique<Die2BTFEntryEnum>(Die);
+ case BTF_KIND_FUNC:
+ case BTF_KIND_FUNC_PROTO:
+ return make_unique<Die2BTFEntryFunc>(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;
+}
+unsigned char 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) {
+ unsigned char Kind = getDieKind(Die);
+
+ switch (Kind) {
+ case BTF_KIND_CONST:
+ case BTF_KIND_FWD:
+ case BTF_KIND_PTR:
+ case BTF_KIND_RESTRICT:
+ case BTF_KIND_TYPEDEF:
+ case BTF_KIND_VOLATILE:
+ break;
+ default:
+ assert("Invalid Die passed into BTFTypeEntry()");
+ break;
+ }
+
+ 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;
+ }
+
+ unsigned char Kind = getDieKind(Die);
+ if (Kind != BTF_KIND_FWD) {
+ BTFType.name_off = 0;
+ } else {
+ auto NameV = Die.findAttribute(dwarf::DW_AT_name);
+ auto Str = NameV.getDIEString().getString();
+ BTFType.name_off = Dwarf2BTF.addBTFString(Str);
+ }
+
+ auto typeEntry = make_unique<BTFTypeEntry>(Id, BTFType);
+ Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
+}
+
+Die2BTFEntryInt::Die2BTFEntryInt(const DIE &Die) : Die2BTFEntry(Die) {
+ unsigned char Kind = getDieKind(Die);
+
+ switch (Kind) {
+ case BTF_KIND_INT:
+ break;
+ default:
+ assert("Invalid Die passed into BTFTypeEntryInt()");
+ break;
+ }
+
+ // handle BTF_INT_ENCODING in IntVal
+ auto Encoding = Die2BTFEntry::getBaseTypeEncoding(Die);
+ assert((Encoding != BTF_INVALID_ENCODING) &&
+ "Invalid Die passed to BTFTypeEntryInt()");
+ __u32 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);
+ __u32 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.name_off = Dwarf2BTF.addBTFString(Str);
+
+ auto typeEntry = make_unique<BTFTypeEntryInt>(Id, BTFType, IntVal);
+ Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
+}
+
+Die2BTFEntryEnum::Die2BTFEntryEnum(const DIE &Die) : Die2BTFEntry(Die) {
+ // get btf_type.size
+ auto V = Die.findAttribute(dwarf::DW_AT_byte_size);
+ __u32 Size = V.getDIEInteger().getValue() & 0xffffffff;
+
+ int 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.name_off = Dwarf2BTF.addBTFString(Str);
+ } else
+ BTFType.name_off = 0;
+
+ for (auto &ChildDie : Die.children()) {
+ struct btf_enum BTFEnum;
+ auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name);
+ auto Str = ChildNameV.getDIEString().getString();
+
+ BTFEnum.name_off = Dwarf2BTF.addBTFString(Str);
+ auto ChildValueV = ChildDie.findAttribute(dwarf::DW_AT_const_value);
+ BTFEnum.val = (__s32)(ChildValueV.getDIEInteger().getValue());
+
+ EnumValues.push_back(BTFEnum);
+ }
+
+ auto typeEntry = make_unique<BTFTypeEntryEnum>(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.name_off = Dwarf2BTF.addBTFString(Str);
+
+ auto &ArrayTypeDie = Die.findAttribute(dwarf::DW_AT_type).getDIEEntry().getEntry();
+ ArrayInfo.type = 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.index_type = Dwarf2BTF.getTypeIndex(TypeDie);
+ IsFirstSubrange = false;
+ }
+ auto CountV = ChildDie.findAttribute(dwarf::DW_AT_count);
+ if (CountV.getType() == DIEValue::isNone) {
+ // array like a[] which essentially a pointer
+ Nelems = 0;
+ break;
+ }
+ Nelems *= (__u32)(CountV.getDIEInteger().getValue());
+ }
+ }
+ ArrayInfo.nelems = Nelems;
+
+ auto TypeEntry = make_unique<BTFTypeEntryArray>(Id, BTFType, ArrayInfo);
+ Dwarf2BTF.addBTFTypeEntry(std::move(TypeEntry));
+}
+
+Die2BTFEntryStruct::Die2BTFEntryStruct(const DIE &Die) : Die2BTFEntry(Die) {
+ // get btf_type.size
+ auto V = Die.findAttribute(dwarf::DW_AT_byte_size);
+ __u32 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.name_off = Dwarf2BTF.addBTFString(Str);
+ } else
+ BTFType.name_off = 0;
+
+
+ for (auto &ChildDie : Die.children()) {
+ if (ChildDie.getTag() != dwarf::DW_TAG_member)
+ continue;
+
+ struct btf_member BTFMember;
+ auto ChildNameV = ChildDie.findAttribute(dwarf::DW_AT_name);
+
+ if (ChildNameV.getType() != DIEValue::isNone) {
+ auto Str = ChildNameV.getDIEString().getString();
+ BTFMember.name_off = Dwarf2BTF.addBTFString(Str);
+ } else
+ BTFMember.name_off = 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 = make_unique<BTFTypeEntryStruct>(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++;
+
+ 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.name_off = 0;
+ } else {
+ auto Str = NameV.getDIEString().getString();
+ BTFType.name_off = 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 = make_unique<BTFTypeEntryFunc>(Id, BTFType, Parameters);
+ Dwarf2BTF.addBTFTypeEntry(std::move(typeEntry));
+
+ if (BTF_INFO_KIND(BTFType.info) == BTF_KIND_FUNC) {
+ 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<MCSectionELF>(&Section);
+ assert(SectionELF);
+ SecNameOff = Dwarf2BTF.addBTFString(SectionELF->getSectionName().str());
+ } else {
+ SecNameOff = Dwarf2BTF.addBTFString(".text");
+ }
+ Dwarf2BTF.addBTFFuncInfo(SecNameOff, FuncInfo);
+ }
+ }
+}
+
+Dwarf2BTF::Dwarf2BTF(MCContext &Context, bool IsLittleEndian)
+ : OuterCtx(Context), IsLE(IsLittleEndian) {
+ BTFContext = make_unique<MCBTFContext>();
+}
+
+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*>(&Die)] = TypeEntry->getId();
+ TypeEntries.push_back(std::move(TypeEntry));
+ }
+ }
+}
+
+void Dwarf2BTF::addBTFTypeEntry(std::unique_ptr<BTFTypeEntry> 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));
+}
+
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.h b/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.h
new file mode 100644
index 00000000000..3df4dd802a7
--- /dev/null
+++ b/llvm/lib/CodeGen/AsmPrinter/Dwarf2BTF.h
@@ -0,0 +1,134 @@
+//===- 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 <map>
+
+namespace llvm {
+
+class Dwarf2BTF;
+class MCBTFContext;
+
+#define BTF_INVALID_ENCODING 0xff
+
+class Die2BTFEntry {
+protected:
+ const DIE &Die;
+ size_t Id; /* type index in the BTF list, started from 1 */
+ struct btf_type BTFType;
+
+public:
+ // Return desired BTF_KIND for the Die, return BTF_KIND_UNKN for
+ // invalid/unsupported Die
+ static unsigned char getDieKind(const DIE &Die);
+
+ // Return proper BTF_INT_ENCODING of a basetype.
+ // Return BTF_INVALID_ENCODING for unsupported (float, etc.)
+ static unsigned char 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);
+
+ static std::unique_ptr<Die2BTFEntry> 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);
+};
+
+// BTF_KIND_INT
+class Die2BTFEntryInt : public Die2BTFEntry {
+ __u32 IntVal; // encoding, offset, bits
+
+public:
+ Die2BTFEntryInt(const DIE &Die);
+ void completeData(class Dwarf2BTF &Dwarf2BTF);
+};
+
+// BTF_KIND_ENUM
+class Die2BTFEntryEnum : public Die2BTFEntry {
+ std::vector<struct btf_enum> EnumValues;
+
+public:
+ Die2BTFEntryEnum(const DIE &Die);
+ void completeData(class Dwarf2BTF &Dwarf2BTF);
+};
+
+// BTF_KIND_ARRAY
+class Die2BTFEntryArray : public Die2BTFEntry {
+ struct btf_array ArrayInfo;
+
+public:
+ Die2BTFEntryArray(const DIE &Die);
+ void completeData(class Dwarf2BTF &Dwarf2BTF);
+};
+
+// BTF_KIND_STRUCT and BTF_KIND_UNION
+class Die2BTFEntryStruct : public Die2BTFEntry {
+ std::vector<struct btf_member> Members;
+
+public:
+ Die2BTFEntryStruct(const DIE &Die);
+ void completeData(class Dwarf2BTF &Dwarf2BTF);
+};
+
+// BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
+class Die2BTFEntryFunc : public Die2BTFEntry {
+ std::vector<__u32> Parameters;
+
+public:
+ Die2BTFEntryFunc(const DIE &Die);
+ void completeData(class Dwarf2BTF &Dwarf2BTF);
+};
+
+class Dwarf2BTF {
+ std::vector<std::unique_ptr<Die2BTFEntry>> TypeEntries;
+ std::map<DIE*, size_t> DieToIdMap;
+ std::unique_ptr<MCBTFContext> BTFContext;
+ MCContext &OuterCtx;
+ bool IsLE;
+
+public:
+ Dwarf2BTF(MCContext &Context, bool IsLittleEndian);
+ bool isLittleEndian() { return IsLE; }
+ void addDwarfCU(DwarfUnit *TheU);
+ void finish();
+ __u32 getTypeIndex(DIE &Die) {
+ DIE *DiePtr = const_cast<DIE*>(&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<BTFTypeEntry> Entry);
+ void addBTFFuncInfo(unsigned SecNameOff, BTFFuncInfo FuncInfo) {
+ BTFContext->addFuncInfo(SecNameOff, FuncInfo);
+ }
+
+private:
+ void addTypeEntry(const DIE &Die);
+ bool alreadyAdded(DIE &Die) {
+ return DieToIdMap.find(const_cast<DIE*>(&Die)) != DieToIdMap.end();
+ }
+ void completeData();
+};
+
+}
+#endif
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 94e12658cfe..184ec4dabe9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -971,6 +971,10 @@ void DwarfDebug::endModule() {
// Emit the pubnames and pubtypes sections if requested.
emitDebugPubSections();
+ const Triple &TT = Asm->TM.getTargetTriple();
+ if (TT.getArch() == Triple::bpfel || TT.getArch() == Triple::bpfeb)
+ emitBTFSection(TT.getArch() == Triple::bpfel);
+
// clean up.
// FIXME: AbstractVariables.clear();
}
@@ -2455,6 +2459,12 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
return &SplitTypeUnitFileTable;
}
+void DwarfDebug::emitBTFSection(bool IsLittleEndian) {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+
+ Holder.emitBTFSection(IsLittleEndian);
+}
+
uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
MD5 Hash;
Hash.update(Identifier);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index fecf8056765..1350317db02 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -567,6 +567,9 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit the reference to the section.
void emitSectionReference(const DwarfCompileUnit &CU);
+ // Emit the BTF sections
+ void emitBTFSection(bool IsLittleEndian);
+
protected:
/// Gather pre-function debug information.
void beginFunctionImpl(const MachineFunction *MF) override;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index 0ab9ea87c23..7ac16b34c4c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "Dwarf2BTF.h"
#include "DwarfFile.h"
#include "DwarfCompileUnit.h"
#include "DwarfDebug.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 <algorithm>
#include <cstdint>
@@ -88,6 +91,13 @@ void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
}
+void DwarfFile::emitBTFSection(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();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index c315f44a8d8..9aafe2613f6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -114,6 +114,9 @@ public:
void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr,
bool UseRelativeOffsets = false);
+ // Emit all data for the BTF section
+ void emitBTFSection(bool IsLittleEndian);
+
/// Returns the string pool.
DwarfStringPool &getStringPool() { return StrPool; }
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index ba36d99e8f7..85bf1616fd6 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -10,11 +10,13 @@ add_llvm_library(LLVMMC
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
diff --git a/llvm/lib/MC/MCBTFContext.cpp b/llvm/lib/MC/MCBTFContext.cpp
new file mode 100644
index 00000000000..cb846ee5e51
--- /dev/null
+++ b/llvm/lib/MC/MCBTFContext.cpp
@@ -0,0 +1,235 @@
+//===- 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/MCContext.h"
+#include "llvm/MC/MCBTFContext.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+#include <tuple>
+#include <utility>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "btf"
+
+void MCBTFContext::addTypeEntry(std::unique_ptr<BTFTypeEntry> Entry) {
+ TypeEntries.push_back(std::move(Entry));
+}
+
+void MCBTFContext::dump(raw_ostream &OS) {
+ OS << "Type Table:\n";
+ for (size_t i = 0; i < TypeEntries.size(); i++) {
+ auto TypeEntry = TypeEntries[i].get();
+ TypeEntry->print(OS, *this);
+ }
+
+ OS << "\nString Table:\n";
+ StringTable.showTable(OS);
+
+ OS << "\nFuncInfo Table:\n";
+ for (auto &FuncSec : FuncInfoTable) {
+ OS << "sec_name_off=" << FuncSec.first << "\n";
+ for (auto &FuncInfo : FuncSec.second) {
+ OS << "\tinsn_offset=<Omitted> type_id="
+ << FuncInfo.TypeId << "\n";
+ }
+ }
+
+ OS << "\nLineInfo Table:\n";
+ for (auto &LineSec : LineInfoTable) {
+ OS << "sec_name_off=" << LineSec.first << "\n";
+ for (auto &LineInfo : LineSec.second) {
+ OS << "\tinsn_offset=<Omitted> file_name_off="
+ << LineInfo.FileNameOff
+ << " line_off=" << LineInfo.LineOff
+ << " line_num=" << LineInfo.LineNum
+ << " column_num=" << 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 btf_header), 4);
+
+ uint32_t type_len = 0, str_len;
+ for (auto &TypeEntry : TypeEntries)
+ type_len += TypeEntry->getSize();
+ str_len = StringTable.getSize();
+
+ MCOS->EmitIntValue(0, 4);
+ MCOS->EmitIntValue(type_len, 4);
+ MCOS->EmitIntValue(type_len, 4);
+ MCOS->EmitIntValue(str_len, 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 btf_ext_header), 4);
+
+ uint32_t func_len = 0, line_len = 0;
+ for (auto &FuncSec : FuncInfoTable) {
+ func_len += sizeof(struct btf_sec_func_info);
+ func_len += FuncSec.second.size() * sizeof(struct bpf_func_info);
+ }
+ for (auto &LineSec : LineInfoTable) {
+ line_len += sizeof(struct btf_sec_line_info);
+ line_len += LineSec.second.size() * sizeof(struct bpf_line_info);
+ }
+
+ MCOS->EmitIntValue(0, 4);
+ MCOS->EmitIntValue(func_len, 4);
+ MCOS->EmitIntValue(func_len, 4);
+ MCOS->EmitIntValue(line_len, 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::emitAll(MCObjectStreamer *MCOS) {
+ LLVM_DEBUG(dump(dbgs()));
+ emitBTFSection(MCOS);
+ emitBTFExtSection(MCOS);
+}
+
+void BTFTypeEntry::print(raw_ostream &OS, MCBTFContext& MCBTFContext) {
+ OS << "[" << Id << "] "
+ << btf_kind_str[BTF_INFO_KIND(BTFType.info)]
+ << " name_off=" << BTFType.name_off
+ << " info=" << format("0x%08lx", BTFType.info)
+ << " size/type=" << BTFType.size << "\n";
+}
+
+void BTFTypeEntry::emitData(MCObjectStreamer *MCOS) {
+ MCOS->EmitIntValue(BTFType.name_off, 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 < BTF_INFO_VLEN(BTFType.info); i++) {
+ auto &EnumValue = EnumValues[i];
+ OS << "\tname_off=" << EnumValue.name_off
+ << " value=" << EnumValue.val << "\n";
+ }
+}
+
+void BTFTypeEntryEnum::emitData(MCObjectStreamer *MCOS) {
+ BTFTypeEntry::emitData(MCOS);
+ for (auto &EnumValue : EnumValues) {
+ MCOS->EmitIntValue(EnumValue.name_off, 4);
+ MCOS->EmitIntValue(EnumValue.val, 4);
+ }
+}
+
+void BTFTypeEntryArray::print(raw_ostream &OS, MCBTFContext& MCBTFContext) {
+ BTFTypeEntry::print(OS, MCBTFContext);
+ OS << "\telem_type=" << format("0x%08lx", ArrayInfo.type)
+ << " index_type=" << format("0x%08lx", ArrayInfo.index_type)
+ << " num_element=" << ArrayInfo.nelems << "\n";
+}
+
+void BTFTypeEntryArray::emitData(MCObjectStreamer *MCOS) {
+ BTFTypeEntry::emitData(MCOS);
+ MCOS->EmitIntValue(ArrayInfo.type, 4);
+ MCOS->EmitIntValue(ArrayInfo.index_type, 4);
+ MCOS->EmitIntValue(ArrayInfo.nelems, 4);
+}
+
+void BTFTypeEntryStruct::print(raw_ostream &OS, MCBTFContext& MCBTFContext) {
+ BTFTypeEntry::print(OS, MCBTFContext);
+ for (size_t i = 0; i < BTF_INFO_VLEN(BTFType.info); i++) {
+ auto &Member = Members[i];
+ OS << "\tname_off=" << Member.name_off
+ << " type=" << Member.type
+ << " bit_offset=" << Member.offset << "\n";
+ }
+}
+
+void BTFTypeEntryStruct::emitData(MCObjectStreamer *MCOS) {
+ BTFTypeEntry::emitData(MCOS);
+ for (auto &Member : Members) {
+ MCOS->EmitIntValue(Member.name_off, 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 < BTF_INFO_VLEN(BTFType.info); i++) {
+ auto Parameter = Parameters[i];
+ OS << "\tparam_type=" << Parameter << "\n";
+ }
+}
+
+void BTFTypeEntryFunc::emitData(MCObjectStreamer *MCOS) {
+ BTFTypeEntry::emitData(MCOS);
+ for (auto &Parameter: Parameters)
+ MCOS->EmitIntValue(Parameter, 4);
+}
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index fab517075c5..18250a474b7 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/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 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
: 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 @@ void MCContext::reset() {
GenDwarfFileNumber = 0;
HadError = false;
+ BTFCtx.reset();
+}
+
+//===----------------------------------------------------------------------===//
+// BTFCtx Manipulation
+//===----------------------------------------------------------------------===//
+void MCContext::setBTFContext(std::unique_ptr<MCBTFContext> Ctx) {
+ BTFCtx = std::move(Ctx);
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/MC/MCDwarf2BTF.cpp b/llvm/lib/MC/MCDwarf2BTF.cpp
new file mode 100644
index 00000000000..08a70e6f318
--- /dev/null
+++ b/llvm/lib/MC/MCDwarf2BTF.cpp
@@ -0,0 +1,99 @@
+//===- 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/MCContext.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCBTFContext.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
+#include <fstream>
+
+using namespace llvm;
+
+void MCDwarf2BTF::addFiles(MCObjectStreamer *MCOS, std::string &FileName,
+ std::vector<FileContent> &Files) {
+ std::vector<std::string> Content;
+
+ std::ifstream Inputfile(FileName);
+ std::string Line;
+ Content.push_back(Line); // line 0 for empty string
+ while (std::getline(Inputfile, Line))
+ Content.push_back(Line);
+
+ Files.push_back(FileContent(FileName, Content));
+}
+
+void MCDwarf2BTF::addLines(MCObjectStreamer *MCOS, StringRef &SectionName,
+ std::vector<FileContent> &Files,
+ const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
+ MCContext &Context = MCOS->getContext();
+ auto &BTFCxt = Context.getBTFContext();
+
+ unsigned SecNameOff = BTFCxt->addString(SectionName.str());
+ 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<std::string> Dirs;
+ std::vector<FileContent> 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);
+ }
+ 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<MCSectionELF>(Section))
+ SectionName = SectionELF->getSectionName();
+ else
+ return;
+ MCDwarf2BTF::addLines(MCOS, SectionName, Files, LineEntries);
+ }
+ }
+}
diff --git a/llvm/lib/MC/MCDwarf2BTF.h b/llvm/lib/MC/MCDwarf2BTF.h
new file mode 100644
index 00000000000..22d1b7741a5
--- /dev/null
+++ b/llvm/lib/MC/MCDwarf2BTF.h
@@ -0,0 +1,29 @@
+//===- 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<std::string, std::vector<std::string>>;
+
+class MCDwarf2BTF {
+public:
+ static void addFiles(MCObjectStreamer *MCOS, std::string &FileName,
+ std::vector<FileContent> &Files);
+ static void addLines(MCObjectStreamer *MCOS, StringRef &SectionName,
+ std::vector<FileContent> &Files,
+ const MCLineSection::MCDwarfLineEntryCollection &LineEntries);
+ static void addDwarfLineInfo(MCObjectStreamer *MCOS);
+};
+
+}
+#endif
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index edfccfcb9ed..bddcf459ac0 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -468,6 +468,9 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
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) {
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 8c88db009bd..4f74f4101c8 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/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 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
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 @@ void MCObjectStreamer::FinishImpl() {
// 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->emitAll(this);
+ BTFCtx.reset();
+ }
+
flushPendingLabels();
getAssembler().Finish();
}
OpenPOWER on IntegriCloud