[ObjectYAML] Support for DWARF __debug_abbrev section

This patch adds support for round-tripping DWARF debug abbreviations through the obj<->yaml tools.

llvm-svn: 288955
This commit is contained in:
Chris Bieneman 2016-12-07 18:52:59 +00:00
parent a913f7ddbe
commit c6c0e54d3d
6 changed files with 571 additions and 3 deletions

View File

@ -23,6 +23,9 @@ class DWARFAbbreviationDeclarationSet {
uint32_t FirstAbbrCode;
std::vector<DWARFAbbreviationDeclaration> Decls;
typedef std::vector<DWARFAbbreviationDeclaration>::const_iterator
const_iterator;
public:
DWARFAbbreviationDeclarationSet();
@ -33,6 +36,14 @@ public:
const DWARFAbbreviationDeclaration *
getAbbreviationDeclaration(uint32_t AbbrCode) const;
const_iterator begin() const {
return Decls.begin();
}
const_iterator end() const {
return Decls.end();
}
private:
void clear();
};
@ -53,6 +64,14 @@ public:
void dump(raw_ostream &OS) const;
void extract(DataExtractor Data);
DWARFAbbreviationDeclarationSetMap::const_iterator begin() const {
return AbbrDeclSets.begin();
}
DWARFAbbreviationDeclarationSetMap::const_iterator end() const {
return AbbrDeclSets.end();
}
private:
void clear();
};

View File

@ -18,6 +18,7 @@
#include "llvm/ObjectYAML/YAML.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/Dwarf.h"
namespace llvm {
namespace MachOYAML {
@ -104,7 +105,20 @@ struct LinkEditData {
bool isEmpty() const;
};
struct DWARFAttributeAbbrev {
llvm::dwarf::Attribute Attribute;
llvm::dwarf::Form Form;
};
struct DWARFAbbrev {
llvm::yaml::Hex32 Code;
llvm::dwarf::Tag Tag;
llvm::dwarf::Constants Children;
std::vector<DWARFAttributeAbbrev> Attributes;
};
struct DWARFData {
std::vector<DWARFAbbrev> AbbrevDecls;
std::vector<StringRef> DebugStrings;
bool isEmpty() const;
@ -153,6 +167,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::NListEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Object)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::FatArch)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::DWARFAttributeAbbrev)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::DWARFAbbrev)
namespace llvm {
namespace yaml {
@ -209,6 +225,14 @@ template <> struct MappingTraits<MachOYAML::DWARFData> {
static void mapping(IO &IO, MachOYAML::DWARFData &DWARF);
};
template <> struct MappingTraits<MachOYAML::DWARFAbbrev> {
static void mapping(IO &IO, MachOYAML::DWARFAbbrev &Abbrev);
};
template <> struct MappingTraits<MachOYAML::DWARFAttributeAbbrev> {
static void mapping(IO &IO, MachOYAML::DWARFAttributeAbbrev &AttAbbrev);
};
#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
io.enumCase(value, #LCName, MachO::LCName);
@ -255,6 +279,44 @@ template <> struct ScalarEnumerationTraits<MachO::BindOpcode> {
}
};
#define HANDLE_DW_TAG(unused, name) \
io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name);
template <> struct ScalarEnumerationTraits<dwarf::Tag> {
static void enumeration(IO &io, dwarf::Tag &value) {
#include "llvm/Support/Dwarf.def"
io.enumFallback<Hex16>(value);
}
};
#define HANDLE_DW_AT(unused, name) \
io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name);
template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
static void enumeration(IO &io, dwarf::Attribute &value) {
#include "llvm/Support/Dwarf.def"
io.enumFallback<Hex16>(value);
}
};
#define HANDLE_DW_FORM(unused, name) \
io.enumCase(value, "DW_FORM_" #name, dwarf::DW_FORM_##name);
template <> struct ScalarEnumerationTraits<dwarf::Form> {
static void enumeration(IO &io, dwarf::Form &value) {
#include "llvm/Support/Dwarf.def"
io.enumFallback<Hex16>(value);
}
};
template <> struct ScalarEnumerationTraits<dwarf::Constants> {
static void enumeration(IO &io, dwarf::Constants &value) {
io.enumCase(value, "DW_CHILDREN_no", dwarf::DW_CHILDREN_no);
io.enumCase(value, "DW_CHILDREN_yes", dwarf::DW_CHILDREN_yes);
io.enumFallback<Hex16>(value);
}
};
// This trait is used for 16-byte chars in Mach structures used for strings
typedef char char_16[16];

View File

@ -30,7 +30,7 @@ bool MachOYAML::LinkEditData::isEmpty() const {
}
bool MachOYAML::DWARFData::isEmpty() const {
return 0 == DebugStrings.size();
return 0 == DebugStrings.size() + AbbrevDecls.size();
}
namespace yaml {
@ -559,7 +559,22 @@ void MappingTraits<MachO::version_min_command>::mapping(
void MappingTraits<MachOYAML::DWARFData>::mapping(
IO &IO, MachOYAML::DWARFData &DWARF) {
IO.mapRequired("DebugStrings", DWARF.DebugStrings);
IO.mapOptional("DebugStrings", DWARF.DebugStrings);
IO.mapOptional("AbbrevDecls", DWARF.AbbrevDecls);
}
void MappingTraits<MachOYAML::DWARFAbbrev>::mapping(
IO &IO, MachOYAML::DWARFAbbrev &Abbrev) {
IO.mapRequired("Code", Abbrev.Code);
IO.mapRequired("Tag", Abbrev.Tag);
IO.mapRequired("Children", Abbrev.Children);
IO.mapRequired("Attributes", Abbrev.Attributes);
}
void MappingTraits<MachOYAML::DWARFAttributeAbbrev>::mapping(
IO &IO, MachOYAML::DWARFAttributeAbbrev &AttAbbrev) {
IO.mapRequired("Attribute", AttAbbrev.Attribute);
IO.mapRequired("Form", AttAbbrev.Form);
}
} // namespace llvm::yaml

View File

@ -0,0 +1,433 @@
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
--- !mach-o
FileHeader:
magic: 0xFEEDFACF
cputype: 0x01000007
cpusubtype: 0x00000003
filetype: 0x0000000A
ncmds: 5
sizeofcmds: 1800
flags: 0x00000000
reserved: 0x00000000
LoadCommands:
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __PAGEZERO
vmaddr: 0
vmsize: 4294967296
fileoff: 0
filesize: 0
maxprot: 0
initprot: 0
nsects: 0
flags: 0
- cmd: LC_SEGMENT_64
cmdsize: 472
segname: __TEXT
vmaddr: 4294967296
vmsize: 4096
fileoff: 0
filesize: 0
maxprot: 7
initprot: 5
nsects: 5
flags: 0
Sections:
- sectname: __text
segname: __TEXT
addr: 0x0000000100000F50
size: 52
offset: 0x00000000
align: 4
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __stubs
segname: __TEXT
addr: 0x0000000100000F84
size: 6
offset: 0x00000000
align: 1
reloff: 0x00000000
nreloc: 0
flags: 0x80000408
reserved1: 0x00000000
reserved2: 0x00000006
reserved3: 0x00000000
- sectname: __stub_helper
segname: __TEXT
addr: 0x0000000100000F8C
size: 26
offset: 0x00000000
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x80000400
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __cstring
segname: __TEXT
addr: 0x0000000100000FA6
size: 14
offset: 0x00000000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000002
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __unwind_info
segname: __TEXT
addr: 0x0000000100000FB4
size: 72
offset: 0x00000000
align: 2
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT_64
cmdsize: 232
segname: __DATA
vmaddr: 4294971392
vmsize: 4096
fileoff: 0
filesize: 0
maxprot: 7
initprot: 3
nsects: 2
flags: 0
Sections:
- sectname: __nl_symbol_ptr
segname: __DATA
addr: 0x0000000100001000
size: 16
offset: 0x00000000
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000006
reserved1: 0x00000001
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __la_symbol_ptr
segname: __DATA
addr: 0x0000000100001010
size: 8
offset: 0x00000000
align: 3
reloff: 0x00000000
nreloc: 0
flags: 0x00000007
reserved1: 0x00000003
reserved2: 0x00000000
reserved3: 0x00000000
- cmd: LC_SEGMENT_64
cmdsize: 72
segname: __LINKEDIT
vmaddr: 4294975488
vmsize: 4096
fileoff: 4096
filesize: 60
maxprot: 7
initprot: 1
nsects: 0
flags: 0
- cmd: LC_SEGMENT_64
cmdsize: 952
segname: __DWARF
vmaddr: 4294979584
vmsize: 4096
fileoff: 8192
filesize: 764
maxprot: 7
initprot: 3
nsects: 11
flags: 0
Sections:
- sectname: __debug_line
segname: __DWARF
addr: 0x0000000100003000
size: 69
offset: 0x00002000
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_pubnames
segname: __DWARF
addr: 0x0000000100003045
size: 27
offset: 0x00002045
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_pubtypes
segname: __DWARF
addr: 0x0000000100003060
size: 35
offset: 0x00002060
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_aranges
segname: __DWARF
addr: 0x0000000100003083
size: 48
offset: 0x00002083
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_info
segname: __DWARF
addr: 0x00000001000030B3
size: 121
offset: 0x000020B3
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_abbrev
segname: __DWARF
addr: 0x000000010000312C
size: 76
offset: 0x0000212C
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __debug_str
segname: __DWARF
addr: 0x0000000100003178
size: 142
offset: 0x00002178
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __apple_names
segname: __DWARF
addr: 0x0000000100003206
size: 60
offset: 0x00002206
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __apple_namespac
segname: __DWARF
addr: 0x0000000100003242
size: 36
offset: 0x00002242
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __apple_types
segname: __DWARF
addr: 0x0000000100003266
size: 114
offset: 0x00002266
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
- sectname: __apple_objc
segname: __DWARF
addr: 0x00000001000032D8
size: 36
offset: 0x000022D8
align: 0
reloff: 0x00000000
nreloc: 0
flags: 0x00000000
reserved1: 0x00000000
reserved2: 0x00000000
reserved3: 0x00000000
DWARF:
AbbrevDecls:
- Code: 0x00000001
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_producer
Form: DW_FORM_strp
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_stmt_list
Form: DW_FORM_sec_offset
- Attribute: DW_AT_comp_dir
Form: DW_FORM_strp
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data4
- Code: 0x00000002
Tag: DW_TAG_subprogram
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_low_pc
Form: DW_FORM_addr
- Attribute: DW_AT_high_pc
Form: DW_FORM_data4
- Attribute: DW_AT_frame_base
Form: DW_FORM_exprloc
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_decl_file
Form: DW_FORM_data1
- Attribute: DW_AT_decl_line
Form: DW_FORM_data1
- Attribute: DW_AT_prototyped
Form: DW_FORM_flag_present
- Attribute: DW_AT_type
Form: DW_FORM_ref4
- Attribute: DW_AT_external
Form: DW_FORM_flag_present
- Code: 0x00000003
Tag: DW_TAG_formal_parameter
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_location
Form: DW_FORM_exprloc
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_decl_file
Form: DW_FORM_data1
- Attribute: DW_AT_decl_line
Form: DW_FORM_data1
- Attribute: DW_AT_type
Form: DW_FORM_ref4
- Code: 0x00000004
Tag: DW_TAG_base_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_encoding
Form: DW_FORM_data1
- Attribute: DW_AT_byte_size
Form: DW_FORM_data1
- Code: 0x00000005
Tag: DW_TAG_pointer_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_type
Form: DW_FORM_ref4
...
#CHECK: DWARF:
#CHECK: AbbrevDecls:
#CHECK: - Code: 0x00000001
#CHECK: Tag: DW_TAG_compile_unit
#CHECK: Children: DW_CHILDREN_yes
#CHECK: Attributes:
#CHECK: - Attribute: DW_AT_producer
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_language
#CHECK: Form: DW_FORM_data2
#CHECK: - Attribute: DW_AT_name
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_stmt_list
#CHECK: Form: DW_FORM_sec_offset
#CHECK: - Attribute: DW_AT_comp_dir
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_low_pc
#CHECK: Form: DW_FORM_addr
#CHECK: - Attribute: DW_AT_high_pc
#CHECK: Form: DW_FORM_data4
#CHECK: - Code: 0x00000002
#CHECK: Tag: DW_TAG_subprogram
#CHECK: Children: DW_CHILDREN_yes
#CHECK: Attributes:
#CHECK: - Attribute: DW_AT_low_pc
#CHECK: Form: DW_FORM_addr
#CHECK: - Attribute: DW_AT_high_pc
#CHECK: Form: DW_FORM_data4
#CHECK: - Attribute: DW_AT_frame_base
#CHECK: Form: DW_FORM_exprloc
#CHECK: - Attribute: DW_AT_name
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_decl_file
#CHECK: Form: DW_FORM_data1
#CHECK: - Attribute: DW_AT_decl_line
#CHECK: Form: DW_FORM_data1
#CHECK: - Attribute: DW_AT_prototyped
#CHECK: Form: DW_FORM_flag_present
#CHECK: - Attribute: DW_AT_type
#CHECK: Form: DW_FORM_ref4
#CHECK: - Attribute: DW_AT_external
#CHECK: Form: DW_FORM_flag_present
#CHECK: - Code: 0x00000003
#CHECK: Tag: DW_TAG_formal_parameter
#CHECK: Children: DW_CHILDREN_no
#CHECK: Attributes:
#CHECK: - Attribute: DW_AT_location
#CHECK: Form: DW_FORM_exprloc
#CHECK: - Attribute: DW_AT_name
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_decl_file
#CHECK: Form: DW_FORM_data1
#CHECK: - Attribute: DW_AT_decl_line
#CHECK: Form: DW_FORM_data1
#CHECK: - Attribute: DW_AT_type
#CHECK: Form: DW_FORM_ref4
#CHECK: - Code: 0x00000004
#CHECK: Tag: DW_TAG_base_type
#CHECK: Children: DW_CHILDREN_no
#CHECK: Attributes:
#CHECK: - Attribute: DW_AT_name
#CHECK: Form: DW_FORM_strp
#CHECK: - Attribute: DW_AT_encoding
#CHECK: Form: DW_FORM_data1
#CHECK: - Attribute: DW_AT_byte_size
#CHECK: Form: DW_FORM_data1
#CHECK: - Code: 0x00000005
#CHECK: Tag: DW_TAG_pointer_type
#CHECK: Children: DW_CHILDREN_no
#CHECK: Attributes:
#CHECK: - Attribute: DW_AT_type
#CHECK: Form: DW_FORM_ref4

View File

@ -36,7 +36,10 @@ class MachODumper {
void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
void dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y);
void dumpDWARF(std::unique_ptr<MachOYAML::Object> &Y);
void dumpDebugStrings(DWARFContextInMemory &DCtx, std::unique_ptr<MachOYAML::Object> &Y);
void dumpDebugAbbrev(DWARFContextInMemory &DCtx,
std::unique_ptr<MachOYAML::Object> &Y);
void dumpDebugStrings(DWARFContextInMemory &DCtx,
std::unique_ptr<MachOYAML::Object> &Y);
public:
MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
@ -466,6 +469,7 @@ void MachODumper::dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y) {
void MachODumper::dumpDWARF(std::unique_ptr<MachOYAML::Object> &Y) {
DWARFContextInMemory DICtx(Obj);
dumpDebugStrings(DICtx, Y);
dumpDebugAbbrev(DICtx, Y);
}
void MachODumper::dumpDebugStrings(DWARFContextInMemory &DICtx,
@ -478,6 +482,29 @@ void MachODumper::dumpDebugStrings(DWARFContextInMemory &DICtx,
}
}
void MachODumper::dumpDebugAbbrev(DWARFContextInMemory &DCtx,
std::unique_ptr<MachOYAML::Object> &Y) {
auto AbbrevSetPtr = DCtx.getDebugAbbrev();
if(AbbrevSetPtr) {
for(auto AbbrvDeclSet : *AbbrevSetPtr) {
for(auto AbbrvDecl : AbbrvDeclSet.second) {
MachOYAML::DWARFAbbrev 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()) {
MachOYAML::DWARFAttributeAbbrev AttAbrv;
AttAbrv.Attribute = Attribute.Attr;
AttAbrv.Form = Attribute.Form;
Abbrv.Attributes.push_back(AttAbrv);
}
Y->DWARF.AbbrevDecls.push_back(Abbrv);
}
}
}
}
Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) {
MachODumper Dumper(Obj);
Expected<std::unique_ptr<MachOYAML::Object>> YAML = Dumper.dump();

View File

@ -393,6 +393,18 @@ Error MachOWriter::writeDWARFData(raw_ostream &OS,
OS.write(Str.data(), Str.size());
OS.write('\0');
}
} else if (0 == strncmp(&Section.sectname[0], "__debug_abbrev", 16)) {
for (auto AbbrevDecl : Obj.DWARF.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);
}
encodeULEB128(0, OS);
encodeULEB128(0, OS);
}
}
}
return Error::success();