[llvm] r270724 - [obj2yaml] [yaml2obj] MachO support for rebase opcodes
Chris Bieneman via llvm-commits
llvm-commits at lists.llvm.org
Wed May 25 10:09:08 PDT 2016
Author: cbieneman
Date: Wed May 25 12:09:07 2016
New Revision: 270724
URL: http://llvm.org/viewvc/llvm-project?rev=270724&view=rev
Log:
[obj2yaml] [yaml2obj] MachO support for rebase opcodes
This is the first bit of support for MachO __LINKEDIT segment data.
Added:
llvm/trunk/test/ObjectYAML/MachO/rebase_opcode.yaml
Modified:
llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
llvm/trunk/tools/obj2yaml/macho2yaml.cpp
llvm/trunk/tools/yaml2obj/yaml2macho.cpp
Modified: llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h?rev=270724&r1=270723&r2=270724&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h Wed May 25 12:09:07 2016
@@ -57,10 +57,21 @@ struct LoadCommand {
uint64_t ZeroPadBytes;
};
+struct RebaseOpcode {
+ MachO::RebaseOpcode Opcode;
+ uint8_t Imm;
+ std::vector<yaml::Hex64> ExtraData;
+};
+
+struct LinkEditData {
+ std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes;
+};
+
struct Object {
FileHeader Header;
std::vector<LoadCommand> LoadCommands;
std::vector<Section> Sections;
+ LinkEditData LinkEdit;
};
} // namespace llvm::MachOYAML
@@ -69,6 +80,8 @@ struct Object {
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode)
namespace llvm {
namespace yaml {
@@ -85,6 +98,14 @@ template <> struct MappingTraits<MachOYA
static void mapping(IO &IO, MachOYAML::LoadCommand &LoadCommand);
};
+template <> struct MappingTraits<MachOYAML::LinkEditData> {
+ static void mapping(IO &IO, MachOYAML::LinkEditData &LinkEditData);
+};
+
+template <> struct MappingTraits<MachOYAML::RebaseOpcode> {
+ static void mapping(IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode);
+};
+
template <> struct MappingTraits<MachOYAML::Section> {
static void mapping(IO &IO, MachOYAML::Section &Section);
};
@@ -99,6 +120,24 @@ template <> struct ScalarEnumerationTrai
}
};
+#define ENUM_CASE(Enum) \
+ io.enumCase(value, #Enum, MachO::Enum);
+
+template <> struct ScalarEnumerationTraits<MachO::RebaseOpcode> {
+ static void enumeration(IO &io, MachO::RebaseOpcode &value) {
+ ENUM_CASE(REBASE_OPCODE_DONE)
+ ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM)
+ ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB)
+ ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB)
+ ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
+ ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB)
+ io.enumFallback<Hex8>(value);
+ }
+};
+
// This trait is used for 16-byte chars in Mach structures used for strings
typedef char char_16[16];
Modified: llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/MachOYAML.cpp?rev=270724&r1=270723&r2=270724&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/MachOYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/MachOYAML.cpp Wed May 25 12:09:07 2016
@@ -93,9 +93,22 @@ void MappingTraits<MachOYAML::Object>::m
}
IO.mapRequired("FileHeader", Object.Header);
IO.mapOptional("LoadCommands", Object.LoadCommands);
+ IO.mapOptional("LinkEditData", Object.LinkEdit);
IO.setContext(nullptr);
}
+void MappingTraits<MachOYAML::LinkEditData>::mapping(IO &IO,
+ MachOYAML::LinkEditData &LinkEditData) {
+ IO.mapOptional("RebaseOpcodes", LinkEditData.RebaseOpcodes);
+}
+
+void MappingTraits<MachOYAML::RebaseOpcode>::mapping(IO &IO,
+ MachOYAML::RebaseOpcode &RebaseOpcode) {
+ IO.mapRequired("Opcode", RebaseOpcode.Opcode);
+ IO.mapRequired("Imm", RebaseOpcode.Imm);
+ IO.mapOptional("ExtraData", RebaseOpcode.ExtraData);
+}
+
template <typename StructType>
void mapLoadCommandData(IO &IO, MachOYAML::LoadCommand &LoadCommand) {}
Added: llvm/trunk/test/ObjectYAML/MachO/rebase_opcode.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/MachO/rebase_opcode.yaml?rev=270724&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/MachO/rebase_opcode.yaml (added)
+++ llvm/trunk/test/ObjectYAML/MachO/rebase_opcode.yaml Wed May 25 12:09:07 2016
@@ -0,0 +1,92 @@
+# RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 4
+ sizeofcmds: 224
+ flags: 0x00218085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4294979584
+ vmsize: 4096
+ fileoff: 1024
+ filesize: 2508
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_DYLD_INFO_ONLY
+ cmdsize: 48
+ rebase_off: 1024
+ rebase_size: 8
+ bind_off: 1032
+ bind_size: 96
+ weak_bind_off: 0
+ weak_bind_size: 0
+ lazy_bind_off: 1128
+ lazy_bind_size: 624
+ export_off: 1752
+ export_size: 48
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 1816
+ nsyms: 30
+ stroff: 2436
+ strsize: 1096
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 9
+ iextdefsym: 9
+ nextdefsym: 2
+ iundefsym: 11
+ nundefsym: 19
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 2296
+ nindirectsyms: 35
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+LinkEditData:
+ RebaseOpcodes:
+ - Opcode: REBASE_OPCODE_SET_TYPE_IMM
+ Imm: 1
+ - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+ Imm: 2
+ ExtraData:
+ - 0x0000000000000028
+ - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+ Imm: 0
+ ExtraData:
+ - 0x000000000000000F
+ - Opcode: REBASE_OPCODE_DONE
+ Imm: 0
+...
+
+#CHECK: LinkEditData:
+#CHECK: RebaseOpcodes:
+#CHECK: - Opcode: REBASE_OPCODE_SET_TYPE_IMM
+#CHECK: Imm: 1
+#CHECK: - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+#CHECK: Imm: 2
+#CHECK: ExtraData:
+#CHECK: - 0x0000000000000028
+#CHECK: - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
+#CHECK: Imm: 0
+#CHECK: ExtraData:
+#CHECK: - 0x000000000000000F
+#CHECK: - Opcode: REBASE_OPCODE_DONE
+#CHECK: Imm: 0
Modified: llvm/trunk/tools/obj2yaml/macho2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/macho2yaml.cpp?rev=270724&r1=270723&r2=270724&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/macho2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/macho2yaml.cpp Wed May 25 12:09:07 2016
@@ -12,6 +12,7 @@
#include "llvm/Object/MachOUniversal.h"
#include "llvm/ObjectYAML/MachOYAML.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
#include <string.h> // for memcpy
@@ -25,6 +26,9 @@ class MachODumper {
const llvm::object::MachOObjectFile::LoadCommandInfo &LoadCmd);
const object::MachOObjectFile &Obj;
+ void dumpHeader(std::unique_ptr<MachOYAML::Object> &Y);
+ void dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y);
+ void dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y);
public:
MachODumper(const object::MachOObjectFile &O) : Obj(O) {}
@@ -144,6 +148,13 @@ const char *MachODumper::processLoadComm
Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
auto Y = make_unique<MachOYAML::Object>();
+ dumpHeader(Y);
+ dumpLoadCommands(Y);
+ dumpLinkEdit(Y);
+ return std::move(Y);
+}
+
+void MachODumper::dumpHeader(std::unique_ptr<MachOYAML::Object> &Y) {
Y->Header.magic = Obj.getHeader().magic;
Y->Header.cputype = Obj.getHeader().cputype;
Y->Header.cpusubtype = Obj.getHeader().cpusubtype;
@@ -152,7 +163,9 @@ Expected<std::unique_ptr<MachOYAML::Obje
Y->Header.sizeofcmds = Obj.getHeader().sizeofcmds;
Y->Header.flags = Obj.getHeader().flags;
Y->Header.reserved = 0;
+}
+void MachODumper::dumpLoadCommands(std::unique_ptr<MachOYAML::Object> &Y) {
for (auto LoadCmd : Obj.load_commands()) {
MachOYAML::LoadCommand LC;
const char *EndPtr = LoadCmd.Ptr;
@@ -176,8 +189,47 @@ Expected<std::unique_ptr<MachOYAML::Obje
LC.ZeroPadBytes = RemainingBytes;
Y->LoadCommands.push_back(std::move(LC));
}
+}
- return std::move(Y);
+void MachODumper::dumpLinkEdit(std::unique_ptr<MachOYAML::Object> &Y) {
+ MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+
+ auto RebaseOpcodes = Obj.getDyldInfoRebaseOpcodes();
+ for (auto OpCode = RebaseOpcodes.begin(); OpCode != RebaseOpcodes.end();
+ ++OpCode) {
+ MachOYAML::RebaseOpcode RebaseOp;
+ RebaseOp.Opcode =
+ static_cast<MachO::RebaseOpcode>(*OpCode & MachO::REBASE_OPCODE_MASK);
+ RebaseOp.Imm = *OpCode & MachO::REBASE_IMMEDIATE_MASK;
+
+ unsigned Count;
+ uint64_t ULEB = 0;
+
+ switch (RebaseOp.Opcode) {
+ case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
+
+ ULEB = decodeULEB128(OpCode + 1, &Count);
+ RebaseOp.ExtraData.push_back(ULEB);
+ OpCode += Count;
+ // Intentionally no break here -- This opcode has two ULEB values
+ case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
+ case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
+ case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
+ case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
+
+ ULEB = decodeULEB128(OpCode + 1, &Count);
+ RebaseOp.ExtraData.push_back(ULEB);
+ OpCode += Count;
+ break;
+ default:
+ break;
+ }
+
+ LEData.RebaseOpcodes.push_back(RebaseOp);
+
+ if (RebaseOp.Opcode == MachO::REBASE_OPCODE_DONE)
+ break;
+ }
}
Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj) {
Modified: llvm/trunk/tools/yaml2obj/yaml2macho.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2macho.cpp?rev=270724&r1=270723&r2=270724&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2macho.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2macho.cpp Wed May 25 12:09:07 2016
@@ -15,10 +15,13 @@
#include "yaml2obj.h"
#include "llvm/ObjectYAML/MachOYAML.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Format.h"
+
using namespace llvm;
namespace {
@@ -42,6 +45,9 @@ private:
Error writeHeader(raw_ostream &OS);
Error writeLoadCommands(raw_ostream &OS);
Error writeSectionData(raw_ostream &OS);
+ Error writeLinkEditData(raw_ostream &OS);
+
+ void ZeroToOffset(raw_ostream &OS, size_t offset);
MachOYAML::Object &Obj;
bool is64Bit;
@@ -165,6 +171,12 @@ void Fill(raw_ostream &OS, size_t Size,
OS.write(reinterpret_cast<char *>(FillData.data()), Size);
}
+void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
+ auto currOffset = OS.tell() - fileStart;
+ if (currOffset < Offset)
+ ZeroFillBytes(OS, Offset - currOffset);
+}
+
Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
for (auto &LC : Obj.LoadCommands) {
size_t BytesWritten = 0;
@@ -212,39 +224,74 @@ Error MachOWriter::writeSectionData(raw_
switch (LC.Data.load_command_data.cmd) {
case MachO::LC_SEGMENT:
case MachO::LC_SEGMENT_64:
+ auto currOffset = OS.tell() - fileStart;
+ auto segname = LC.Data.segment_command_data.segname;
uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
: LC.Data.segment_command_data.fileoff;
- // Zero Fill any data between the end of the last thing we wrote and the
- // start of this section.
- auto currOffset = OS.tell() - fileStart;
- if (currOffset < segOff) {
- ZeroFillBytes(OS, segOff - currOffset);
- }
-
- for (auto &Sec : LC.Sections) {
+ if (0 == strncmp(&segname[0], "__LINKEDIT", 16)) {
+ if (auto Err = writeLinkEditData(OS))
+ return Err;
+ } else {
// Zero Fill any data between the end of the last thing we wrote and the
// start of this section.
- assert(OS.tell() - fileStart <= Sec.offset &&
- "Wrote too much data somewhere, section offsets don't line up.");
- currOffset = OS.tell() - fileStart;
- if (currOffset < Sec.offset) {
- ZeroFillBytes(OS, Sec.offset - currOffset);
+ if (currOffset < segOff) {
+ ZeroFillBytes(OS, segOff - currOffset);
}
- // Fills section data with 0xDEADBEEF
- Fill(OS, Sec.size, 0xDEADBEEFu);
+ for (auto &Sec : LC.Sections) {
+ // Zero Fill any data between the end of the last thing we wrote and
+ // the
+ // start of this section.
+ assert(
+ OS.tell() - fileStart <= Sec.offset &&
+ "Wrote too much data somewhere, section offsets don't line up.");
+ currOffset = OS.tell() - fileStart;
+ if (currOffset < Sec.offset) {
+ ZeroFillBytes(OS, Sec.offset - currOffset);
+ }
+
+ // Fills section data with 0xDEADBEEF
+ Fill(OS, Sec.size, 0xDEADBEEFu);
+ }
}
uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize
: LC.Data.segment_command_data.filesize;
- currOffset = OS.tell() - fileStart;
- if (currOffset < segOff + segSize) {
- // Fills segment data not covered by a section with 0xBAADDA7A
- Fill(OS, (segOff + segSize) - currOffset, 0xBAADDA7Au);
- }
+ ZeroToOffset(OS, segOff + segSize);
+ break;
+ }
+ }
+ return Error::success();
+}
+
+Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
+ MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
+ MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
+ MachO::symtab_command *SymtabCmd = 0;
+ for (auto &LC : Obj.LoadCommands) {
+ switch (LC.Data.load_command_data.cmd) {
+ case MachO::LC_SYMTAB:
+ SymtabCmd = &LC.Data.symtab_command_data;
+ break;
+ case MachO::LC_DYLD_INFO_ONLY:
+ DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
break;
}
}
+
+ ZeroToOffset(OS, DyldInfoOnlyCmd->rebase_off);
+
+ for (auto Opcode : LinkEdit.RebaseOpcodes) {
+ uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
+ OS.write(reinterpret_cast<char *>(&OpByte), 1);
+ for (auto Data : Opcode.ExtraData) {
+ encodeULEB128(Data, OS);
+ }
+ }
+
+ // Fill to the end of the string table
+ ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
+
return Error::success();
}
More information about the llvm-commits
mailing list