From 4a6766e76f0e59a424170da8a5c1ff3d15d3243e Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Tue, 6 Dec 2016 06:00:49 +0000 Subject: [PATCH] [ObjectYAML] First bit of support for encoding DWARF in MachO This patch adds the starting support for encoding data from the MachO __DWARF segment. The first section supported is the __debug_str section because it is the simplest. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288774 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ObjectYAML/MachOYAML.h | 11 + lib/ObjectYAML/MachOYAML.cpp | 17 +- test/ObjectYAML/MachO/DWARF-debug_str.yaml | 266 +++++++++++++++++++++ tools/obj2yaml/CMakeLists.txt | 1 + tools/obj2yaml/macho2yaml.cpp | 19 ++ tools/yaml2obj/yaml2macho.cpp | 22 +- 6 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 test/ObjectYAML/MachO/DWARF-debug_str.yaml diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h index 2fbd71f0bcd6..4de495beb86e 100644 --- a/include/llvm/ObjectYAML/MachOYAML.h +++ b/include/llvm/ObjectYAML/MachOYAML.h @@ -104,11 +104,18 @@ struct LinkEditData { bool isEmpty() const; }; +struct DWARFData { + std::vector DebugStrings; + + bool isEmpty() const; +}; + struct Object { FileHeader Header; std::vector LoadCommands; std::vector
Sections; LinkEditData LinkEdit; + DWARFData DWARF; }; struct FatHeader { @@ -198,6 +205,10 @@ template <> struct MappingTraits { static void mapping(IO &IO, MachOYAML::NListEntry &NListEntry); }; +template <> struct MappingTraits { + static void mapping(IO &IO, MachOYAML::DWARFData &DWARF); +}; + #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ io.enumCase(value, #LCName, MachO::LCName); diff --git a/lib/ObjectYAML/MachOYAML.cpp b/lib/ObjectYAML/MachOYAML.cpp index 984ca0b9d01f..d3f8ea47e595 100644 --- a/lib/ObjectYAML/MachOYAML.cpp +++ b/lib/ObjectYAML/MachOYAML.cpp @@ -23,7 +23,14 @@ namespace llvm { MachOYAML::LoadCommand::~LoadCommand() {} bool MachOYAML::LinkEditData::isEmpty() const { - return 0 == RebaseOpcodes.size() + BindOpcodes.size() + WeakBindOpcodes.size() + LazyBindOpcodes.size() + ExportTrie.Children.size() + NameList.size() + StringTable.size(); + return 0 == + RebaseOpcodes.size() + BindOpcodes.size() + WeakBindOpcodes.size() + + LazyBindOpcodes.size() + ExportTrie.Children.size() + + NameList.size() + StringTable.size(); +} + +bool MachOYAML::DWARFData::isEmpty() const { + return 0 == DebugStrings.size(); } namespace yaml { @@ -102,6 +109,9 @@ void MappingTraits::mapping(IO &IO, if(!Object.LinkEdit.isEmpty() || !IO.outputting()) IO.mapOptional("LinkEditData", Object.LinkEdit); + if(!Object.DWARF.isEmpty() || !IO.outputting()) + IO.mapOptional("DWARF", Object.DWARF); + if (IO.getContext() == &Object) IO.setContext(nullptr); } @@ -547,6 +557,11 @@ void MappingTraits::mapping( IO.mapRequired("sdk", LoadCommand.sdk); } +void MappingTraits::mapping( + IO &IO, MachOYAML::DWARFData &DWARF) { + IO.mapRequired("DebugStrings", DWARF.DebugStrings); +} + } // namespace llvm::yaml } // namespace llvm diff --git a/test/ObjectYAML/MachO/DWARF-debug_str.yaml b/test/ObjectYAML/MachO/DWARF-debug_str.yaml new file mode 100644 index 000000000000..c0557bc7eef6 --- /dev/null +++ b/test/ObjectYAML/MachO/DWARF-debug_str.yaml @@ -0,0 +1,266 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x0000000A + ncmds: 6 + sizeofcmds: 1376 + flags: 0x00000000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_UUID + cmdsize: 24 + uuid: 9304404B-E522-3BBA-A861-AF5938908725 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 4096 + nsyms: 2 + stroff: 4128 + strsize: 28 + - 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: 232 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 0 + maxprot: 7 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000FA0 + size: 22 + offset: 0x00000000 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __unwind_info + segname: __TEXT + addr: 0x0000000100000FB8 + size: 72 + offset: 0x00000000 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294971392 + vmsize: 4096 + fileoff: 4096 + filesize: 60 + maxprot: 7 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SEGMENT_64 + cmdsize: 952 + segname: __DWARF + vmaddr: 4294975488 + vmsize: 4096 + fileoff: 8192 + filesize: 765 + maxprot: 7 + initprot: 3 + nsects: 11 + flags: 0 + Sections: + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000100002000 + size: 70 + offset: 0x00002000 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubnames + segname: __DWARF + addr: 0x0000000100002046 + size: 27 + offset: 0x00002046 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_pubtypes + segname: __DWARF + addr: 0x0000000100002061 + size: 35 + offset: 0x00002061 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_aranges + segname: __DWARF + addr: 0x0000000100002084 + size: 48 + offset: 0x00002084 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000001000020B4 + size: 121 + offset: 0x000020B4 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x000000010000212D + size: 76 + offset: 0x0000212D + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x0000000100002179 + size: 142 + offset: 0x00002179 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_names + segname: __DWARF + addr: 0x0000000100002207 + size: 60 + offset: 0x00002207 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x0000000100002243 + size: 36 + offset: 0x00002243 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_types + segname: __DWARF + addr: 0x0000000100002267 + size: 114 + offset: 0x00002267 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x00000001000022D9 + size: 36 + offset: 0x000022D9 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 +LinkEditData: + NameList: + - n_strx: 2 + n_type: 0x0F + n_sect: 1 + n_desc: 16 + n_value: 4294967296 + - n_strx: 22 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971296 + StringTable: + - '' + - '' + - __mh_execute_header + - _main +DWARF: + DebugStrings: + - '' + - 'clang version 4.0.0 (trunk 288677) (llvm/trunk 288676)' + - hello_world.c + - /Users/cbieneman/dev/open-source/llvm-build-rel + - main + - argc + - argv + - int + - char +... + +#CHECK: DWARF: +#CHECK: DebugStrings: +#CHECK: - '' +#CHECK: - 'clang version 4.0.0 (trunk 288677) (llvm/trunk 288676)' +#CHECK: - hello_world.c +#CHECK: - /Users/cbieneman/dev/open-source/llvm-build-rel +#CHECK: - main +#CHECK: - argc +#CHECK: - argv +#CHECK: - int +#CHECK: - char + diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt index 9b8955250602..813f39960510 100644 --- a/tools/obj2yaml/CMakeLists.txt +++ b/tools/obj2yaml/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + DebugInfoDWARF Object ObjectYAML Support diff --git a/tools/obj2yaml/macho2yaml.cpp b/tools/obj2yaml/macho2yaml.cpp index 3d32aa1b6617..0953d284e11c 100644 --- a/tools/obj2yaml/macho2yaml.cpp +++ b/tools/obj2yaml/macho2yaml.cpp @@ -9,6 +9,7 @@ #include "Error.h" #include "obj2yaml.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/Support/ErrorHandling.h" @@ -34,6 +35,8 @@ class MachODumper { ArrayRef OpcodeBuffer, bool Lazy = false); void dumpExportTrie(std::unique_ptr &Y); void dumpSymbols(std::unique_ptr &Y); + void dumpDWARF(std::unique_ptr &Y); + void dumpDebugStrings(DWARFContextInMemory &DCtx, std::unique_ptr &Y); public: MachODumper(const object::MachOObjectFile &O) : Obj(O) {} @@ -163,6 +166,7 @@ Expected> MachODumper::dump() { dumpHeader(Y); dumpLoadCommands(Y); dumpLinkEdit(Y); + dumpDWARF(Y); return std::move(Y); } @@ -459,6 +463,21 @@ void MachODumper::dumpSymbols(std::unique_ptr &Y) { } } +void MachODumper::dumpDWARF(std::unique_ptr &Y) { + DWARFContextInMemory DICtx(Obj); + dumpDebugStrings(DICtx, Y); +} + +void MachODumper::dumpDebugStrings(DWARFContextInMemory &DICtx, + std::unique_ptr &Y) { + StringRef RemainingTable = DICtx.getStringSection(); + while (RemainingTable.size() > 0) { + auto SymbolPair = RemainingTable.split('\0'); + RemainingTable = SymbolPair.second; + Y->DWARF.DebugStrings.push_back(SymbolPair.first); + } +} + Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) { MachODumper Dumper(Obj); Expected> YAML = Dumper.dump(); diff --git a/tools/yaml2obj/yaml2macho.cpp b/tools/yaml2obj/yaml2macho.cpp index fb29e206be35..3312cd45fb73 100644 --- a/tools/yaml2obj/yaml2macho.cpp +++ b/tools/yaml2obj/yaml2macho.cpp @@ -41,6 +41,8 @@ class MachOWriter { Error writeLoadCommands(raw_ostream &OS); Error writeSectionData(raw_ostream &OS); Error writeLinkEditData(raw_ostream &OS); + Error writeDWARFData(raw_ostream &OS, + std::vector &Sections); void writeBindOpcodes(raw_ostream &OS, std::vector &BindOpcodes); // LinkEdit writers @@ -240,6 +242,9 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) { if (0 == strncmp(&segname[0], "__LINKEDIT", 16)) { if (auto Err = writeLinkEditData(OS)) return Err; + } else if (0 == strncmp(&segname[0], "__DWARF", 16)) { + if (auto Err = writeDWARFData(OS, LC.Sections)) + return Err; } else { // Zero Fill any data between the end of the last thing we wrote and the // start of this section. @@ -252,7 +257,8 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) { // the // start of this section. assert( - OS.tell() - fileStart <= Sec.offset && + (OS.tell() - fileStart <= Sec.offset || + Sec.offset == (uint32_t)0) && "Wrote too much data somewhere, section offsets don't line up."); currOffset = OS.tell() - fileStart; if (currOffset < Sec.offset) { @@ -378,6 +384,20 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) { return Error::success(); } +Error MachOWriter::writeDWARFData(raw_ostream &OS, + std::vector &Sections) { + for(auto Section : Sections) { + ZeroToOffset(OS, Section.offset); + if (0 == strncmp(&Section.sectname[0], "__debug_str", 16)) { + for (auto Str : Obj.DWARF.DebugStrings) { + OS.write(Str.data(), Str.size()); + OS.write('\0'); + } + } + } + return Error::success(); +} + Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) { MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;