You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.207
Former-commit-id: 3b152f462918d427ce18620a2cbe4f8b79650449
This commit is contained in:
parent
8e12397d70
commit
eb85e2fc17
357
external/llvm/tools/obj2yaml/dwarf2yaml.cpp
vendored
357
external/llvm/tools/obj2yaml/dwarf2yaml.cpp
vendored
@ -1,357 +0,0 @@
|
||||
//===------ dwarf2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/ObjectYAML/DWARFYAML.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void dumpInitialLength(DataExtractor &Data, uint32_t &Offset,
|
||||
DWARFYAML::InitialLength &InitialLength) {
|
||||
InitialLength.TotalLength = Data.getU32(&Offset);
|
||||
if (InitialLength.isDWARF64())
|
||||
InitialLength.TotalLength64 = Data.getU64(&Offset);
|
||||
}
|
||||
|
||||
void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
auto AbbrevSetPtr = DCtx.getDebugAbbrev();
|
||||
if (AbbrevSetPtr) {
|
||||
for (auto AbbrvDeclSet : *AbbrevSetPtr) {
|
||||
for (auto AbbrvDecl : AbbrvDeclSet.second) {
|
||||
DWARFYAML::Abbrev Abbrv;
|
||||
Abbrv.Code = AbbrvDecl.getCode();
|
||||
Abbrv.Tag = AbbrvDecl.getTag();
|
||||
Abbrv.Children = AbbrvDecl.hasChildren() ? dwarf::DW_CHILDREN_yes
|
||||
: dwarf::DW_CHILDREN_no;
|
||||
for (auto Attribute : AbbrvDecl.attributes()) {
|
||||
DWARFYAML::AttributeAbbrev AttAbrv;
|
||||
AttAbrv.Attribute = Attribute.Attr;
|
||||
AttAbrv.Form = Attribute.Form;
|
||||
if (AttAbrv.Form == dwarf::DW_FORM_implicit_const)
|
||||
AttAbrv.Value = Attribute.getImplicitConstValue();
|
||||
Abbrv.Attributes.push_back(AttAbrv);
|
||||
}
|
||||
Y.AbbrevDecls.push_back(Abbrv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
StringRef RemainingTable = DCtx.getDWARFObj().getStringSection();
|
||||
while (RemainingTable.size() > 0) {
|
||||
auto SymbolPair = RemainingTable.split('\0');
|
||||
RemainingTable = SymbolPair.second;
|
||||
Y.DebugStrings.push_back(SymbolPair.first);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(),
|
||||
DCtx.isLittleEndian(), 0);
|
||||
uint32_t Offset = 0;
|
||||
DWARFDebugArangeSet Set;
|
||||
|
||||
while (Set.extract(ArangesData, &Offset)) {
|
||||
DWARFYAML::ARange Range;
|
||||
Range.Length.setLength(Set.getHeader().Length);
|
||||
Range.Version = Set.getHeader().Version;
|
||||
Range.CuOffset = Set.getHeader().CuOffset;
|
||||
Range.AddrSize = Set.getHeader().AddrSize;
|
||||
Range.SegSize = Set.getHeader().SegSize;
|
||||
for (auto Descriptor : Set.descriptors()) {
|
||||
DWARFYAML::ARangeDescriptor Desc;
|
||||
Desc.Address = Descriptor.Address;
|
||||
Desc.Length = Descriptor.Length;
|
||||
Range.Descriptors.push_back(Desc);
|
||||
}
|
||||
Y.ARanges.push_back(Range);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
|
||||
StringRef Section) {
|
||||
DataExtractor PubSectionData(Section, DCtx.isLittleEndian(), 0);
|
||||
uint32_t Offset = 0;
|
||||
dumpInitialLength(PubSectionData, Offset, Y.Length);
|
||||
Y.Version = PubSectionData.getU16(&Offset);
|
||||
Y.UnitOffset = PubSectionData.getU32(&Offset);
|
||||
Y.UnitSize = PubSectionData.getU32(&Offset);
|
||||
while (Offset < Y.Length.getLength()) {
|
||||
DWARFYAML::PubEntry NewEntry;
|
||||
NewEntry.DieOffset = PubSectionData.getU32(&Offset);
|
||||
if (Y.IsGNUStyle)
|
||||
NewEntry.Descriptor = PubSectionData.getU8(&Offset);
|
||||
NewEntry.Name = PubSectionData.getCStr(&Offset);
|
||||
Y.Entries.push_back(NewEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
const DWARFObject &D = DCtx.getDWARFObj();
|
||||
Y.PubNames.IsGNUStyle = false;
|
||||
dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection());
|
||||
|
||||
Y.PubTypes.IsGNUStyle = false;
|
||||
dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection());
|
||||
|
||||
Y.GNUPubNames.IsGNUStyle = true;
|
||||
dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection());
|
||||
|
||||
Y.GNUPubTypes.IsGNUStyle = true;
|
||||
dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection());
|
||||
}
|
||||
|
||||
void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
for (const auto &CU : DCtx.compile_units()) {
|
||||
DWARFYAML::Unit NewUnit;
|
||||
NewUnit.Length.setLength(CU->getLength());
|
||||
NewUnit.Version = CU->getVersion();
|
||||
if(NewUnit.Version >= 5)
|
||||
NewUnit.Type = (dwarf::UnitType)CU->getUnitType();
|
||||
NewUnit.AbbrOffset = CU->getAbbreviations()->getOffset();
|
||||
NewUnit.AddrSize = CU->getAddressByteSize();
|
||||
for (auto DIE : CU->dies()) {
|
||||
DWARFYAML::Entry NewEntry;
|
||||
DataExtractor EntryData = CU->getDebugInfoExtractor();
|
||||
uint32_t offset = DIE.getOffset();
|
||||
|
||||
assert(EntryData.isValidOffset(offset) && "Invalid DIE Offset");
|
||||
if (!EntryData.isValidOffset(offset))
|
||||
continue;
|
||||
|
||||
NewEntry.AbbrCode = EntryData.getULEB128(&offset);
|
||||
|
||||
auto AbbrevDecl = DIE.getAbbreviationDeclarationPtr();
|
||||
if (AbbrevDecl) {
|
||||
for (const auto &AttrSpec : AbbrevDecl->attributes()) {
|
||||
DWARFYAML::FormValue NewValue;
|
||||
NewValue.Value = 0xDEADBEEFDEADBEEF;
|
||||
DWARFDie DIEWrapper(CU.get(), &DIE);
|
||||
auto FormValue = DIEWrapper.find(AttrSpec.Attr);
|
||||
if (!FormValue)
|
||||
return;
|
||||
auto Form = FormValue.getValue().getForm();
|
||||
bool indirect = false;
|
||||
do {
|
||||
indirect = false;
|
||||
switch (Form) {
|
||||
case dwarf::DW_FORM_addr:
|
||||
case dwarf::DW_FORM_GNU_addr_index:
|
||||
if (auto Val = FormValue.getValue().getAsAddress())
|
||||
NewValue.Value = Val.getValue();
|
||||
break;
|
||||
case dwarf::DW_FORM_ref_addr:
|
||||
case dwarf::DW_FORM_ref1:
|
||||
case dwarf::DW_FORM_ref2:
|
||||
case dwarf::DW_FORM_ref4:
|
||||
case dwarf::DW_FORM_ref8:
|
||||
case dwarf::DW_FORM_ref_udata:
|
||||
case dwarf::DW_FORM_ref_sig8:
|
||||
if (auto Val = FormValue.getValue().getAsReferenceUVal())
|
||||
NewValue.Value = Val.getValue();
|
||||
break;
|
||||
case dwarf::DW_FORM_exprloc:
|
||||
case dwarf::DW_FORM_block:
|
||||
case dwarf::DW_FORM_block1:
|
||||
case dwarf::DW_FORM_block2:
|
||||
case dwarf::DW_FORM_block4:
|
||||
if (auto Val = FormValue.getValue().getAsBlock()) {
|
||||
auto BlockData = Val.getValue();
|
||||
std::copy(BlockData.begin(), BlockData.end(),
|
||||
std::back_inserter(NewValue.BlockData));
|
||||
}
|
||||
NewValue.Value = NewValue.BlockData.size();
|
||||
break;
|
||||
case dwarf::DW_FORM_data1:
|
||||
case dwarf::DW_FORM_flag:
|
||||
case dwarf::DW_FORM_data2:
|
||||
case dwarf::DW_FORM_data4:
|
||||
case dwarf::DW_FORM_data8:
|
||||
case dwarf::DW_FORM_sdata:
|
||||
case dwarf::DW_FORM_udata:
|
||||
case dwarf::DW_FORM_ref_sup4:
|
||||
case dwarf::DW_FORM_ref_sup8:
|
||||
if (auto Val = FormValue.getValue().getAsUnsignedConstant())
|
||||
NewValue.Value = Val.getValue();
|
||||
break;
|
||||
case dwarf::DW_FORM_string:
|
||||
if (auto Val = FormValue.getValue().getAsCString())
|
||||
NewValue.CStr = Val.getValue();
|
||||
break;
|
||||
case dwarf::DW_FORM_indirect:
|
||||
indirect = true;
|
||||
if (auto Val = FormValue.getValue().getAsUnsignedConstant()) {
|
||||
NewValue.Value = Val.getValue();
|
||||
NewEntry.Values.push_back(NewValue);
|
||||
Form = static_cast<dwarf::Form>(Val.getValue());
|
||||
}
|
||||
break;
|
||||
case dwarf::DW_FORM_strp:
|
||||
case dwarf::DW_FORM_sec_offset:
|
||||
case dwarf::DW_FORM_GNU_ref_alt:
|
||||
case dwarf::DW_FORM_GNU_strp_alt:
|
||||
case dwarf::DW_FORM_line_strp:
|
||||
case dwarf::DW_FORM_strp_sup:
|
||||
case dwarf::DW_FORM_GNU_str_index:
|
||||
case dwarf::DW_FORM_strx:
|
||||
if (auto Val = FormValue.getValue().getAsCStringOffset())
|
||||
NewValue.Value = Val.getValue();
|
||||
break;
|
||||
case dwarf::DW_FORM_flag_present:
|
||||
NewValue.Value = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (indirect);
|
||||
NewEntry.Values.push_back(NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
NewUnit.Entries.push_back(NewEntry);
|
||||
}
|
||||
Y.CompileUnits.push_back(NewUnit);
|
||||
}
|
||||
}
|
||||
|
||||
bool dumpFileEntry(DataExtractor &Data, uint32_t &Offset,
|
||||
DWARFYAML::File &File) {
|
||||
File.Name = Data.getCStr(&Offset);
|
||||
if (File.Name.empty())
|
||||
return false;
|
||||
File.DirIdx = Data.getULEB128(&Offset);
|
||||
File.ModTime = Data.getULEB128(&Offset);
|
||||
File.Length = Data.getULEB128(&Offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
for (const auto &CU : DCtx.compile_units()) {
|
||||
auto CUDIE = CU->getUnitDIE();
|
||||
if (!CUDIE)
|
||||
continue;
|
||||
if (auto StmtOffset =
|
||||
dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
|
||||
DWARFYAML::LineTable DebugLines;
|
||||
DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
|
||||
DCtx.isLittleEndian(), CU->getAddressByteSize());
|
||||
uint32_t Offset = *StmtOffset;
|
||||
dumpInitialLength(LineData, Offset, DebugLines.Length);
|
||||
uint64_t LineTableLength = DebugLines.Length.getLength();
|
||||
uint64_t SizeOfPrologueLength = DebugLines.Length.isDWARF64() ? 8 : 4;
|
||||
DebugLines.Version = LineData.getU16(&Offset);
|
||||
DebugLines.PrologueLength =
|
||||
LineData.getUnsigned(&Offset, SizeOfPrologueLength);
|
||||
const uint64_t EndPrologue = DebugLines.PrologueLength + Offset;
|
||||
|
||||
DebugLines.MinInstLength = LineData.getU8(&Offset);
|
||||
if (DebugLines.Version >= 4)
|
||||
DebugLines.MaxOpsPerInst = LineData.getU8(&Offset);
|
||||
DebugLines.DefaultIsStmt = LineData.getU8(&Offset);
|
||||
DebugLines.LineBase = LineData.getU8(&Offset);
|
||||
DebugLines.LineRange = LineData.getU8(&Offset);
|
||||
DebugLines.OpcodeBase = LineData.getU8(&Offset);
|
||||
|
||||
DebugLines.StandardOpcodeLengths.reserve(DebugLines.OpcodeBase - 1);
|
||||
for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i)
|
||||
DebugLines.StandardOpcodeLengths.push_back(LineData.getU8(&Offset));
|
||||
|
||||
while (Offset < EndPrologue) {
|
||||
StringRef Dir = LineData.getCStr(&Offset);
|
||||
if (!Dir.empty())
|
||||
DebugLines.IncludeDirs.push_back(Dir);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
while (Offset < EndPrologue) {
|
||||
DWARFYAML::File TmpFile;
|
||||
if (dumpFileEntry(LineData, Offset, TmpFile))
|
||||
DebugLines.Files.push_back(TmpFile);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
const uint64_t LineEnd =
|
||||
LineTableLength + *StmtOffset + SizeOfPrologueLength;
|
||||
while (Offset < LineEnd) {
|
||||
DWARFYAML::LineTableOpcode NewOp;
|
||||
NewOp.Opcode = (dwarf::LineNumberOps)LineData.getU8(&Offset);
|
||||
if (NewOp.Opcode == 0) {
|
||||
auto StartExt = Offset;
|
||||
NewOp.ExtLen = LineData.getULEB128(&Offset);
|
||||
NewOp.SubOpcode =
|
||||
(dwarf::LineNumberExtendedOps)LineData.getU8(&Offset);
|
||||
switch (NewOp.SubOpcode) {
|
||||
case dwarf::DW_LNE_set_address:
|
||||
case dwarf::DW_LNE_set_discriminator:
|
||||
NewOp.Data = LineData.getAddress(&Offset);
|
||||
break;
|
||||
case dwarf::DW_LNE_define_file:
|
||||
dumpFileEntry(LineData, Offset, NewOp.FileEntry);
|
||||
break;
|
||||
case dwarf::DW_LNE_end_sequence:
|
||||
break;
|
||||
default:
|
||||
while (Offset < StartExt + NewOp.ExtLen)
|
||||
NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset));
|
||||
}
|
||||
} else if (NewOp.Opcode < DebugLines.OpcodeBase) {
|
||||
switch (NewOp.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:
|
||||
NewOp.Data = LineData.getULEB128(&Offset);
|
||||
break;
|
||||
|
||||
case dwarf::DW_LNS_advance_line:
|
||||
NewOp.SData = LineData.getSLEB128(&Offset);
|
||||
break;
|
||||
|
||||
case dwarf::DW_LNS_fixed_advance_pc:
|
||||
NewOp.Data = LineData.getU16(&Offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
for (uint8_t i = 0;
|
||||
i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i)
|
||||
NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
|
||||
}
|
||||
}
|
||||
DebugLines.Opcodes.push_back(NewOp);
|
||||
}
|
||||
Y.DebugLines.push_back(DebugLines);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
|
||||
dumpDebugAbbrev(DCtx, Y);
|
||||
dumpDebugStrings(DCtx, Y);
|
||||
dumpDebugARanges(DCtx, Y);
|
||||
dumpDebugPubSections(DCtx, Y);
|
||||
dumpDebugInfo(DCtx, Y);
|
||||
dumpDebugLines(DCtx, Y);
|
||||
return obj2yaml_error::success;
|
||||
}
|
Reference in New Issue
Block a user