1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===------ macho2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===// 2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The LLVM Compiler Infrastructure 4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details. 7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "Error.h" 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "obj2yaml.h" 12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Object/MachOUniversal.h" 13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/ObjectYAML/ObjectYAML.h" 14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/ErrorHandling.h" 15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/LEB128.h" 16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <string.h> // for memcpy 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm; 20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass MachODumper { 22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar template <typename StructType> 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const char *processLoadCommandData( 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd); 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const object::MachOObjectFile &Obj; 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpHeader(std::unique_ptr<MachOYAML::Object> &Y); 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y); 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y); 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y); 33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpBindOpcodes(std::vector<MachOYAML::BindOpcode> &BindOpcodes, 34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ArrayRef<uint8_t> OpcodeBuffer, bool Lazy = false); 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y); 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y); 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic: 39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachODumper(const object::MachOObjectFile &O) : Obj(O) {} 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Expected<std::unique_ptr<MachOYAML::Object>> dump(); 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}; 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::LCName: \ 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy((void *) & (LC.Data.LCStruct##_data), LoadCmd.Ptr, \ 46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar sizeof(MachO::LCStruct)); \ 47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Obj.isLittleEndian() != sys::IsLittleEndianHost) \ 48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachO::swapStruct(LC.Data.LCStruct##_data); \ 49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar EndPtr = processLoadCommandData<MachO::LCStruct>(LC, LoadCmd); \ 50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename SectionType> 53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarMachOYAML::Section constructSectionCommon(SectionType Sec) { 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::Section TempSec; 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16); 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16); 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.addr = Sec.addr; 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.size = Sec.size; 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.offset = Sec.offset; 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.align = Sec.align; 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reloff = Sec.reloff; 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.nreloc = Sec.nreloc; 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.flags = Sec.flags; 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reserved1 = Sec.reserved1; 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reserved2 = Sec.reserved2; 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reserved3 = 0; 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return TempSec; 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename SectionType> 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarMachOYAML::Section constructSection(SectionType Sec); 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> MachOYAML::Section constructSection(MachO::section Sec) { 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::Section TempSec = constructSectionCommon(Sec); 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reserved3 = 0; 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return TempSec; 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> MachOYAML::Section constructSection(MachO::section_64 Sec) { 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::Section TempSec = constructSectionCommon(Sec); 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TempSec.reserved3 = Sec.reserved3; 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return TempSec; 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename SectionType, typename SegmentType> 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char * 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarextractSections(const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd, 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::vector<MachOYAML::Section> &Sections, 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool IsLittleEndian) { 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize; 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const SectionType *Curr = 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType)); 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (; reinterpret_cast<const void *>(Curr) < End; Curr++) { 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (IsLittleEndian != sys::IsLittleEndianHost) { 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SectionType Sec; 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy((void *)&Sec, Curr, sizeof(SectionType)); 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachO::swapStruct(Sec); 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Sections.push_back(constructSection(Sec)); 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else { 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Sections.push_back(constructSection(*Curr)); 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return reinterpret_cast<const char *>(Curr); 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename StructType> 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData( 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return LoadCmd.Ptr + sizeof(StructType); 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData<MachO::segment_command>( 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return extractSections<MachO::section, MachO::segment_command>( 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LoadCmd, LC.Sections, Obj.isLittleEndian()); 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData<MachO::segment_command_64>( 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return extractSections<MachO::section_64, MachO::segment_command_64>( 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LoadCmd, LC.Sections, Obj.isLittleEndian()); 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename StructType> 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char * 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarreadString(MachOYAML::LoadCommand &LC, 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto Start = LoadCmd.Ptr + sizeof(StructType); 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto MaxSize = LoadCmd.C.cmdsize - sizeof(StructType); 135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto Size = strnlen(Start, MaxSize); 136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LC.PayloadString = StringRef(Start, Size).str(); 137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Start + Size; 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData<MachO::dylib_command>( 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return readString<MachO::dylib_command>(LC, LoadCmd); 145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData<MachO::dylinker_command>( 149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return readString<MachO::dylinker_command>(LC, LoadCmd); 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <> 155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst char *MachODumper::processLoadCommandData<MachO::rpath_command>( 156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand &LC, 157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd) { 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return readString<MachO::rpath_command>(LC, LoadCmd); 159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarExpected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() { 162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto Y = make_unique<MachOYAML::Object>(); 163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpHeader(Y); 164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpLoadCommands(Y); 165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpLinkEdit(Y); 166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return std::move(Y); 167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpHeader(std::unique_ptr<MachOYAML::Object> &Y) { 170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.magic = Obj.getHeader().magic; 171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.cputype = Obj.getHeader().cputype; 172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.cpusubtype = Obj.getHeader().cpusubtype; 173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.filetype = Obj.getHeader().filetype; 174de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.ncmds = Obj.getHeader().ncmds; 175de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.sizeofcmds = Obj.getHeader().sizeofcmds; 176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.flags = Obj.getHeader().flags; 177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->Header.reserved = 0; 178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 180de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y) { 181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto LoadCmd : Obj.load_commands()) { 182de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LoadCommand LC; 183de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const char *EndPtr = LoadCmd.Ptr; 184de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar switch (LoadCmd.C.cmd) { 185de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar default: 186de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy((void *)&(LC.Data.load_command_data), LoadCmd.Ptr, 187de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar sizeof(MachO::load_command)); 188de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Obj.isLittleEndian() != sys::IsLittleEndianHost) 189de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachO::swapStruct(LC.Data.load_command_data); 190de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar EndPtr = processLoadCommandData<MachO::load_command>(LC, LoadCmd); 191de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 192de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/MachO.def" 193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto RemainingBytes = LoadCmd.C.cmdsize - (EndPtr - LoadCmd.Ptr); 195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!std::all_of(EndPtr, &EndPtr[RemainingBytes], 196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar [](const char C) { return C == 0; })) { 197de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LC.PayloadBytes.insert(LC.PayloadBytes.end(), EndPtr, 198de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar &EndPtr[RemainingBytes]); 199de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RemainingBytes = 0; 200de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LC.ZeroPadBytes = RemainingBytes; 202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Y->LoadCommands.push_back(std::move(LC)); 203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) { 207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpRebaseOpcodes(Y); 208de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpBindOpcodes(Y->LinkEdit.BindOpcodes, Obj.getDyldInfoBindOpcodes()); 209de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpBindOpcodes(Y->LinkEdit.WeakBindOpcodes, 210de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Obj.getDyldInfoWeakBindOpcodes()); 211de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpBindOpcodes(Y->LinkEdit.LazyBindOpcodes, Obj.getDyldInfoLazyBindOpcodes(), 212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar true); 213de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpExportTrie(Y); 214de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar dumpSymbols(Y); 215de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 216de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 217de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpRebaseOpcodes(std::unique_ptr<MachOYAML::Object> &Y) { 218de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LinkEditData &LEData = Y->LinkEdit; 219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto RebaseOpcodes = Obj.getDyldInfoRebaseOpcodes(); 221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto OpCode = RebaseOpcodes.begin(); OpCode != RebaseOpcodes.end(); 222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ++OpCode) { 223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::RebaseOpcode RebaseOp; 224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RebaseOp.Opcode = 225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar static_cast<MachO::RebaseOpcode>(*OpCode & MachO::REBASE_OPCODE_MASK); 226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RebaseOp.Imm = *OpCode & MachO::REBASE_IMMEDIATE_MASK; 227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Count; 229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint64_t ULEB = 0; 230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar switch (RebaseOp.Opcode) { 232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 233de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 234de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ULEB = decodeULEB128(OpCode + 1, &Count); 235de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RebaseOp.ExtraData.push_back(ULEB); 236de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += Count; 237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Intentionally no break here -- This opcode has two ULEB values 238de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 239de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 242de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 243de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ULEB = decodeULEB128(OpCode + 1, &Count); 244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RebaseOp.ExtraData.push_back(ULEB); 245de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += Count; 246de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 247de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar default: 248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 249de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 250de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 251de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LEData.RebaseOpcodes.push_back(RebaseOp); 252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (RebaseOp.Opcode == MachO::REBASE_OPCODE_DONE) 254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarStringRef ReadStringRef(const uint8_t *Start) { 259de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const uint8_t *Itr = Start; 260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (; *Itr; ++Itr) 261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ; 262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return StringRef(reinterpret_cast<const char *>(Start), Itr - Start); 263de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 264de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 265de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpBindOpcodes( 266de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::vector<MachOYAML::BindOpcode> &BindOpcodes, 267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ArrayRef<uint8_t> OpcodeBuffer, bool Lazy) { 268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto OpCode = OpcodeBuffer.begin(); OpCode != OpcodeBuffer.end(); 269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ++OpCode) { 270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::BindOpcode BindOp; 271de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.Opcode = 272de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar static_cast<MachO::BindOpcode>(*OpCode & MachO::BIND_OPCODE_MASK); 273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.Imm = *OpCode & MachO::BIND_IMMEDIATE_MASK; 274de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 275de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Count; 276de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint64_t ULEB = 0; 277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int64_t SLEB = 0; 278de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 279de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar switch (BindOp.Opcode) { 280de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 281de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ULEB = decodeULEB128(OpCode + 1, &Count); 282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.ULEBExtraData.push_back(ULEB); 283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += Count; 284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Intentionally no break here -- this opcode has two ULEB values 285de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 288de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 289de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 290de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ULEB = decodeULEB128(OpCode + 1, &Count); 291de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.ULEBExtraData.push_back(ULEB); 292de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += Count; 293de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 294de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 295de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 296de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SLEB = decodeSLEB128(OpCode + 1, &Count); 297de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.SLEBExtraData.push_back(SLEB); 298de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += Count; 299de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 300de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 301de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 302de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOp.Symbol = ReadStringRef(OpCode + 1); 303de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar OpCode += BindOp.Symbol.size() + 1; 304de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 305de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar default: 306de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 307de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 308de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 309de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BindOpcodes.push_back(BindOp); 310de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 311de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Lazy bindings have DONE opcodes between operations, so we need to keep 312de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // processing after a DONE. 313de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Lazy && BindOp.Opcode == MachO::BIND_OPCODE_DONE) 314de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 315de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 316de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 317de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 318de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar/*! 319de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * /brief processes a node from the export trie, and its children. 320de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 321de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * To my knowledge there is no documentation of the encoded format of this data 322de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * other than in the heads of the Apple linker engineers. To that end hopefully 323de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * this comment and the implementation below can serve to light the way for 324de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * anyone crazy enough to come down this path in the future. 325de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 326de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * This function reads and preserves the trie structure of the export trie. To 327de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * my knowledge there is no code anywhere else that reads the data and preserves 328de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * the Trie. LD64 (sources available at opensource.apple.com) has a similar 329de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * implementation that parses the export trie into a vector. That code as well 330de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * as LLVM's libObject MachO implementation were the basis for this. 331de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 332de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * The export trie is an encoded trie. The node serialization is a bit awkward. 333de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * The below pseudo-code is the best description I've come up with for it. 334de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 335de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * struct SerializedNode { 336de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ULEB128 TerminalSize; 337de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * struct TerminalData { <-- This is only present if TerminalSize > 0 338de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ULEB128 Flags; 339de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ULEB128 Address; <-- Present if (! Flags & REEXPORT ) 340de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ULEB128 Other; <-- Present if ( Flags & REEXPORT || 341de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * Flags & STUB_AND_RESOLVER ) 342de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * char[] ImportName; <-- Present if ( Flags & REEXPORT ) 343de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * } 344de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * uint8_t ChildrenCount; 345de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * Pair<char[], ULEB128> ChildNameOffsetPair[ChildrenCount]; 346de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * SerializedNode Children[ChildrenCount] 347de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * } 348de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 349de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * Terminal nodes are nodes that represent actual exports. They can appear 350de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * anywhere in the tree other than at the root; they do not need to be leaf 351de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * nodes. When reading the data out of the trie this routine reads it in-order, 352de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * but it puts the child names and offsets directly into the child nodes. This 353de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * results in looping over the children twice during serialization and 354de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * de-serialization, but it makes the YAML representation more human readable. 355de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 356de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * Below is an example of the graph from a "Hello World" executable: 357de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 358de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------- 359de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | '' | 360de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------- 361de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | 362de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------- 363de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | '_' | 364de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------- 365de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | 366de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * |----------------------------------------| 367de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | | 368de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------------------------ --------------------- 369de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | '_mh_execute_header' | | 'main' | 370de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | Flags: 0x00000000 | | Flags: 0x00000000 | 371de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * | Addr: 0x00000000 | | Addr: 0x00001160 | 372de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * ------------------------ --------------------- 373de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * 374de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * This graph represents the trie for the exports "__mh_execute_header" and 375de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * "_main". In the graph only the "_main" and "__mh_execute_header" nodes are 376de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar * terminal. 377de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar*/ 378de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 379de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst uint8_t *processExportNode(const uint8_t *CurrPtr, 380de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const uint8_t *const End, 381de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::ExportEntry &Entry) { 382de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (CurrPtr >= End) 383de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return CurrPtr; 384de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned Count = 0; 385de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.TerminalSize = decodeULEB128(CurrPtr, &Count); 386de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 387de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Entry.TerminalSize != 0) { 388de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Flags = decodeULEB128(CurrPtr, &Count); 389de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 390de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 391de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Address = 0; 392de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Other = decodeULEB128(CurrPtr, &Count); 393de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 394de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.ImportName = std::string(reinterpret_cast<const char *>(CurrPtr)); 395de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else { 396de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Address = decodeULEB128(CurrPtr, &Count); 397de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 398de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) { 399de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Other = decodeULEB128(CurrPtr, &Count); 400de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 401de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else 402de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Other = 0; 403de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 404de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 405de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint8_t childrenCount = *CurrPtr++; 406de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (childrenCount == 0) 407de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return CurrPtr; 408de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 409de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Entry.Children.insert(Entry.Children.begin(), (size_t)childrenCount, 410de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::ExportEntry()); 411de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &Child : Entry.Children) { 412de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Child.Name = std::string(reinterpret_cast<const char *>(CurrPtr)); 413de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Child.Name.length() + 1; 414de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Child.NodeOffset = decodeULEB128(CurrPtr, &Count); 415de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr += Count; 416de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 417de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &Child : Entry.Children) { 418de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CurrPtr = processExportNode(CurrPtr, End, Child); 419de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 420de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return CurrPtr; 421de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 422de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 423de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y) { 424de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LinkEditData &LEData = Y->LinkEdit; 425de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto ExportsTrie = Obj.getDyldInfoExportsTrie(); 426de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar processExportNode(ExportsTrie.begin(), ExportsTrie.end(), LEData.ExportTrie); 427de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 428de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 429de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename nlist_t> 430de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarMachOYAML::NListEntry constructNameList(const nlist_t &nlist) { 431de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::NListEntry NL; 432de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NL.n_strx = nlist.n_strx; 433de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NL.n_type = nlist.n_type; 434de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NL.n_sect = nlist.n_sect; 435de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NL.n_desc = nlist.n_desc; 436de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NL.n_value = nlist.n_value; 437de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return NL; 438de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 439de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 440de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid MachODumper::dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y) { 441de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::LinkEditData &LEData = Y->LinkEdit; 442de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 443de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto Symbol : Obj.symbols()) { 444de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::NListEntry NLE = 445de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Obj.is64Bit() ? constructNameList<MachO::nlist_64>( 446de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar *reinterpret_cast<const MachO::nlist_64 *>( 447de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Symbol.getRawDataRefImpl().p)) 448de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : constructNameList<MachO::nlist>( 449de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar *reinterpret_cast<const MachO::nlist *>( 450de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Symbol.getRawDataRefImpl().p)); 451de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LEData.NameList.push_back(NLE); 452de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 453de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 454de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef RemainingTable = Obj.getStringTableData(); 455de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar while (RemainingTable.size() > 0) { 456de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto SymbolPair = RemainingTable.split('\0'); 457de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar RemainingTable = SymbolPair.second; 458de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (SymbolPair.first.empty()) 459de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar break; 460de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LEData.StringTable.push_back(SymbolPair.first); 461de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 462de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 463de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 464de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarError macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) { 465de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachODumper Dumper(Obj); 466de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Expected<std::unique_ptr<MachOYAML::Object>> YAML = Dumper.dump(); 467de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!YAML) 468de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return YAML.takeError(); 469de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 470de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar yaml::YamlObjectFile YAMLFile; 471de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAMLFile.MachO = std::move(YAML.get()); 472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar yaml::Output Yout(Out); 474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Yout << YAMLFile; 475de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Error::success(); 476de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 477de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 478de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarError macho2yaml(raw_ostream &Out, const object::MachOUniversalBinary &Obj) { 479de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar yaml::YamlObjectFile YAMLFile; 480de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAMLFile.FatMachO.reset(new MachOYAML::UniversalBinary()); 481de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::UniversalBinary &YAML = *YAMLFile.FatMachO; 482de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAML.Header.magic = Obj.getMagic(); 483de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAML.Header.nfat_arch = Obj.getNumberOfObjects(); 484de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 485de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto Slice : Obj.objects()) { 486de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachOYAML::FatArch arch; 487de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.cputype = Slice.getCPUType(); 488de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.cpusubtype = Slice.getCPUSubType(); 489de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.offset = Slice.getOffset(); 490de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.size = Slice.getSize(); 491de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.align = Slice.getAlign(); 492de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar arch.reserved = Slice.getReserved(); 493de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAML.FatArchs.push_back(arch); 494de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 495de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto SliceObj = Slice.getAsObjectFile(); 496de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!SliceObj) 497de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return SliceObj.takeError(); 498de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 499de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar MachODumper Dumper(*SliceObj.get()); 500de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Expected<std::unique_ptr<MachOYAML::Object>> YAMLObj = Dumper.dump(); 501de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!YAMLObj) 502de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return YAMLObj.takeError(); 503de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar YAML.Slices.push_back(*YAMLObj.get()); 504de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 505de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 506de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar yaml::Output Yout(Out); 507de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Yout << YAML; 508de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Error::success(); 509de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 510de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 511de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstd::error_code macho2yaml(raw_ostream &Out, const object::Binary &Binary) { 512de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (const auto *MachOObj = dyn_cast<object::MachOUniversalBinary>(&Binary)) { 513de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto Err = macho2yaml(Out, *MachOObj)) { 514de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorToErrorCode(std::move(Err)); 515de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 516de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return obj2yaml_error::success; 517de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 518de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 519de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (const auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Binary)) { 520de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto Err = macho2yaml(Out, *MachOObj)) { 521de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return errorToErrorCode(std::move(Err)); 522de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 523de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return obj2yaml_error::success; 524de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 525de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 526de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return obj2yaml_error::unsupported_obj_file_format; 527de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 528