summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-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
7 files changed, 412 insertions, 1 deletions
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