diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/CMakeLists.txt | 2 | ||||
-rw-r--r-- | llvm/lib/MC/MCBTFContext.cpp | 235 | ||||
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/MC/MCDwarf2BTF.cpp | 99 | ||||
-rw-r--r-- | llvm/lib/MC/MCDwarf2BTF.h | 29 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectFileInfo.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 34 |
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(); } |