mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
eb66b33867
I did this a long time ago with a janky python script, but now clang-format has built-in support for this. I fed clang-format every line with a #include and let it re-sort things according to the precise LLVM rules for include ordering baked into clang-format these days. I've reverted a number of files where the results of sorting includes isn't healthy. Either places where we have legacy code relying on particular include ordering (where possible, I'll fix these separately) or where we have particular formatting around #include lines that I didn't want to disturb in this patch. This patch is *entirely* mechanical. If you get merge conflicts or anything, just ignore the changes in this patch and run clang-format over your #include lines in the files. Sorry for any noise here, but it is important to keep these things stable. I was seeing an increasing number of patches with irrelevant re-ordering of #include lines because clang-format was used. This patch at least isolates that churn, makes it easy to skip when resolving conflicts, and gets us to a clean baseline (again). llvm-svn: 304787
322 lines
11 KiB
C++
322 lines
11 KiB
C++
//===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief The DWARF component of yaml2obj. Provided as library code for tests.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ObjectYAML/DWARFEmitter.h"
|
|
#include "llvm/ObjectYAML/DWARFYAML.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/LEB128.h"
|
|
#include "llvm/Support/SwapByteOrder.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "DWARFVisitor.h"
|
|
|
|
#include <algorithm>
|
|
|
|
using namespace llvm;
|
|
|
|
template <typename T>
|
|
static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
|
|
if (IsLittleEndian != sys::IsLittleEndianHost)
|
|
sys::swapByteOrder(Integer);
|
|
OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
|
|
}
|
|
|
|
static void writeVariableSizedInteger(uint64_t Integer, size_t Size,
|
|
raw_ostream &OS, bool IsLittleEndian) {
|
|
if (8 == Size)
|
|
writeInteger((uint64_t)Integer, OS, IsLittleEndian);
|
|
else if (4 == Size)
|
|
writeInteger((uint32_t)Integer, OS, IsLittleEndian);
|
|
else if (2 == Size)
|
|
writeInteger((uint16_t)Integer, OS, IsLittleEndian);
|
|
else if (1 == Size)
|
|
writeInteger((uint8_t)Integer, OS, IsLittleEndian);
|
|
else
|
|
assert(false && "Invalid integer write size.");
|
|
}
|
|
|
|
static void ZeroFillBytes(raw_ostream &OS, size_t Size) {
|
|
std::vector<uint8_t> FillData;
|
|
FillData.insert(FillData.begin(), Size, 0);
|
|
OS.write(reinterpret_cast<char *>(FillData.data()), Size);
|
|
}
|
|
|
|
void writeInitialLength(const DWARFYAML::InitialLength &Length, raw_ostream &OS,
|
|
bool IsLittleEndian) {
|
|
writeInteger((uint32_t)Length.TotalLength, OS, IsLittleEndian);
|
|
if (Length.isDWARF64())
|
|
writeInteger((uint64_t)Length.TotalLength64, OS, IsLittleEndian);
|
|
}
|
|
|
|
void DWARFYAML::EmitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|
for (auto Str : DI.DebugStrings) {
|
|
OS.write(Str.data(), Str.size());
|
|
OS.write('\0');
|
|
}
|
|
}
|
|
|
|
void DWARFYAML::EmitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|
for (auto AbbrevDecl : DI.AbbrevDecls) {
|
|
encodeULEB128(AbbrevDecl.Code, OS);
|
|
encodeULEB128(AbbrevDecl.Tag, OS);
|
|
OS.write(AbbrevDecl.Children);
|
|
for (auto Attr : AbbrevDecl.Attributes) {
|
|
encodeULEB128(Attr.Attribute, OS);
|
|
encodeULEB128(Attr.Form, OS);
|
|
if (Attr.Form == dwarf::DW_FORM_implicit_const)
|
|
encodeSLEB128(Attr.Value, OS);
|
|
}
|
|
encodeULEB128(0, OS);
|
|
encodeULEB128(0, OS);
|
|
}
|
|
}
|
|
|
|
void DWARFYAML::EmitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|
for (auto Range : DI.ARanges) {
|
|
auto HeaderStart = OS.tell();
|
|
writeInitialLength(Range.Length, OS, DI.IsLittleEndian);
|
|
writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
|
|
writeInteger((uint32_t)Range.CuOffset, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)Range.AddrSize, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
|
|
|
|
auto HeaderSize = OS.tell() - HeaderStart;
|
|
auto FirstDescriptor = alignTo(HeaderSize, Range.AddrSize * 2);
|
|
ZeroFillBytes(OS, FirstDescriptor - HeaderSize);
|
|
|
|
for (auto Descriptor : Range.Descriptors) {
|
|
writeVariableSizedInteger(Descriptor.Address, Range.AddrSize, OS,
|
|
DI.IsLittleEndian);
|
|
writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS,
|
|
DI.IsLittleEndian);
|
|
}
|
|
ZeroFillBytes(OS, Range.AddrSize * 2);
|
|
}
|
|
}
|
|
|
|
void DWARFYAML::EmitPubSection(raw_ostream &OS,
|
|
const DWARFYAML::PubSection &Sect,
|
|
bool IsLittleEndian) {
|
|
writeInitialLength(Sect.Length, OS, IsLittleEndian);
|
|
writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
|
|
writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
|
|
writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
|
|
for (auto Entry : Sect.Entries) {
|
|
writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
|
|
if (Sect.IsGNUStyle)
|
|
writeInteger((uint32_t)Entry.Descriptor, OS, IsLittleEndian);
|
|
OS.write(Entry.Name.data(), Entry.Name.size());
|
|
OS.write('\0');
|
|
}
|
|
}
|
|
|
|
/// \brief An extension of the DWARFYAML::ConstVisitor which writes compile
|
|
/// units and DIEs to a stream.
|
|
class DumpVisitor : public DWARFYAML::ConstVisitor {
|
|
raw_ostream &OS;
|
|
|
|
protected:
|
|
virtual void onStartCompileUnit(const DWARFYAML::Unit &CU) {
|
|
writeInitialLength(CU.Length, OS, DebugInfo.IsLittleEndian);
|
|
writeInteger((uint16_t)CU.Version, OS, DebugInfo.IsLittleEndian);
|
|
if(CU.Version >= 5) {
|
|
writeInteger((uint8_t)CU.Type, OS, DebugInfo.IsLittleEndian);
|
|
writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
|
|
writeInteger((uint32_t)CU.AbbrOffset, OS, DebugInfo.IsLittleEndian);
|
|
}else {
|
|
writeInteger((uint32_t)CU.AbbrOffset, OS, DebugInfo.IsLittleEndian);
|
|
writeInteger((uint8_t)CU.AddrSize, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
|
|
}
|
|
|
|
virtual void onStartDIE(const DWARFYAML::Unit &CU,
|
|
const DWARFYAML::Entry &DIE) {
|
|
encodeULEB128(DIE.AbbrCode, OS);
|
|
}
|
|
|
|
virtual void onValue(const uint8_t U) {
|
|
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
|
|
virtual void onValue(const uint16_t U) {
|
|
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
virtual void onValue(const uint32_t U) {
|
|
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
virtual void onValue(const uint64_t U, const bool LEB = false) {
|
|
if (LEB)
|
|
encodeULEB128(U, OS);
|
|
else
|
|
writeInteger(U, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
|
|
virtual void onValue(const int64_t S, const bool LEB = false) {
|
|
if (LEB)
|
|
encodeSLEB128(S, OS);
|
|
else
|
|
writeInteger(S, OS, DebugInfo.IsLittleEndian);
|
|
}
|
|
|
|
virtual void onValue(const StringRef String) {
|
|
OS.write(String.data(), String.size());
|
|
OS.write('\0');
|
|
}
|
|
|
|
virtual void onValue(const MemoryBufferRef MBR) {
|
|
OS.write(MBR.getBufferStart(), MBR.getBufferSize());
|
|
}
|
|
|
|
public:
|
|
DumpVisitor(const DWARFYAML::Data &DI, raw_ostream &Out)
|
|
: DWARFYAML::ConstVisitor(DI), OS(Out) {}
|
|
};
|
|
|
|
void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|
DumpVisitor Visitor(DI, OS);
|
|
Visitor.traverseDebugInfo();
|
|
}
|
|
|
|
static void EmitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
|
|
OS.write(File.Name.data(), File.Name.size());
|
|
OS.write('\0');
|
|
encodeULEB128(File.DirIdx, OS);
|
|
encodeULEB128(File.ModTime, OS);
|
|
encodeULEB128(File.Length, OS);
|
|
}
|
|
|
|
void DWARFYAML::EmitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
|
|
for (const auto &LineTable : DI.DebugLines) {
|
|
writeInitialLength(LineTable.Length, OS, DI.IsLittleEndian);
|
|
uint64_t SizeOfPrologueLength = LineTable.Length.isDWARF64() ? 8 : 4;
|
|
writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian);
|
|
writeVariableSizedInteger(LineTable.PrologueLength, SizeOfPrologueLength,
|
|
OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian);
|
|
if (LineTable.Version >= 4)
|
|
writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)LineTable.DefaultIsStmt, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)LineTable.LineBase, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)LineTable.LineRange, OS, DI.IsLittleEndian);
|
|
writeInteger((uint8_t)LineTable.OpcodeBase, OS, DI.IsLittleEndian);
|
|
|
|
for (auto OpcodeLength : LineTable.StandardOpcodeLengths)
|
|
writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian);
|
|
|
|
for (auto IncludeDir : LineTable.IncludeDirs) {
|
|
OS.write(IncludeDir.data(), IncludeDir.size());
|
|
OS.write('\0');
|
|
}
|
|
OS.write('\0');
|
|
|
|
for (auto File : LineTable.Files)
|
|
EmitFileEntry(OS, File);
|
|
OS.write('\0');
|
|
|
|
for (auto Op : LineTable.Opcodes) {
|
|
writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian);
|
|
if (Op.Opcode == 0) {
|
|
encodeULEB128(Op.ExtLen, OS);
|
|
writeInteger((uint8_t)Op.SubOpcode, OS, DI.IsLittleEndian);
|
|
switch (Op.SubOpcode) {
|
|
case dwarf::DW_LNE_set_address:
|
|
case dwarf::DW_LNE_set_discriminator:
|
|
writeVariableSizedInteger(Op.Data, DI.CompileUnits[0].AddrSize, OS,
|
|
DI.IsLittleEndian);
|
|
break;
|
|
case dwarf::DW_LNE_define_file:
|
|
EmitFileEntry(OS, Op.FileEntry);
|
|
break;
|
|
case dwarf::DW_LNE_end_sequence:
|
|
break;
|
|
default:
|
|
for (auto OpByte : Op.UnknownOpcodeData)
|
|
writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian);
|
|
}
|
|
} else if (Op.Opcode < LineTable.OpcodeBase) {
|
|
switch (Op.Opcode) {
|
|
case dwarf::DW_LNS_copy:
|
|
case dwarf::DW_LNS_negate_stmt:
|
|
case dwarf::DW_LNS_set_basic_block:
|
|
case dwarf::DW_LNS_const_add_pc:
|
|
case dwarf::DW_LNS_set_prologue_end:
|
|
case dwarf::DW_LNS_set_epilogue_begin:
|
|
break;
|
|
|
|
case dwarf::DW_LNS_advance_pc:
|
|
case dwarf::DW_LNS_set_file:
|
|
case dwarf::DW_LNS_set_column:
|
|
case dwarf::DW_LNS_set_isa:
|
|
encodeULEB128(Op.Data, OS);
|
|
break;
|
|
|
|
case dwarf::DW_LNS_advance_line:
|
|
encodeSLEB128(Op.SData, OS);
|
|
break;
|
|
|
|
case dwarf::DW_LNS_fixed_advance_pc:
|
|
writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian);
|
|
break;
|
|
|
|
default:
|
|
for (auto OpData : Op.StandardOpcodeData) {
|
|
encodeULEB128(OpData, OS);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef void (*EmitFuncType)(raw_ostream &, const DWARFYAML::Data &);
|
|
|
|
static void
|
|
EmitDebugSectionImpl(const DWARFYAML::Data &DI, EmitFuncType EmitFunc,
|
|
StringRef Sec,
|
|
StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
|
|
std::string Data;
|
|
raw_string_ostream DebugInfoStream(Data);
|
|
EmitFunc(DebugInfoStream, DI);
|
|
DebugInfoStream.flush();
|
|
if (!Data.empty())
|
|
OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
|
|
}
|
|
|
|
Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
|
|
DWARFYAML::EmitDebugSections(StringRef YAMLString,
|
|
bool IsLittleEndian) {
|
|
StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
|
|
|
|
yaml::Input YIn(YAMLString);
|
|
|
|
DWARFYAML::Data DI;
|
|
DI.IsLittleEndian = IsLittleEndian;
|
|
YIn >> DI;
|
|
if (YIn.error())
|
|
return errorCodeToError(YIn.error());
|
|
|
|
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugInfo, "debug_info",
|
|
DebugSections);
|
|
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugLine, "debug_line",
|
|
DebugSections);
|
|
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugStr, "debug_str",
|
|
DebugSections);
|
|
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAbbrev, "debug_abbrev",
|
|
DebugSections);
|
|
EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAranges, "debug_aranges",
|
|
DebugSections);
|
|
return std::move(DebugSections);
|
|
}
|