| Chris Bieneman | b83c187 | 2016-05-11 22:07:48 +0000 | [diff] [blame] | 1 | //===- yaml2macho - Convert YAML to a Mach object file --------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | /// | 
|  | 10 | /// \file | 
|  | 11 | /// \brief The Mach component of yaml2obj. | 
|  | 12 | /// | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "yaml2obj.h" | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 16 | #include "llvm/ObjectYAML/ObjectYAML.h" | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 17 | #include "llvm/ObjectYAML/DWARFEmitter.h" | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 18 | #include "llvm/Support/Error.h" | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 19 | #include "llvm/Support/LEB128.h" | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 20 | #include "llvm/Support/MachO.h" | 
|  | 21 | #include "llvm/Support/YAMLTraits.h" | 
| Chris Bieneman | b83c187 | 2016-05-11 22:07:48 +0000 | [diff] [blame] | 22 | #include "llvm/Support/raw_ostream.h" | 
|  | 23 |  | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Format.h" | 
|  | 25 |  | 
| Chris Bieneman | b83c187 | 2016-05-11 22:07:48 +0000 | [diff] [blame] | 26 | using namespace llvm; | 
|  | 27 |  | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 28 | namespace { | 
|  | 29 |  | 
|  | 30 | class MachOWriter { | 
|  | 31 | public: | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 32 | MachOWriter(MachOYAML::Object &Obj) : Obj(Obj), is64Bit(true), fileStart(0) { | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 33 | is64Bit = Obj.Header.magic == MachO::MH_MAGIC_64 || | 
|  | 34 | Obj.Header.magic == MachO::MH_CIGAM_64; | 
| Chris Bieneman | 468208a | 2016-06-06 21:18:43 +0000 | [diff] [blame] | 35 | memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64)); | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 36 | } | 
|  | 37 |  | 
|  | 38 | Error writeMachO(raw_ostream &OS); | 
|  | 39 |  | 
|  | 40 | private: | 
|  | 41 | Error writeHeader(raw_ostream &OS); | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 42 | Error writeLoadCommands(raw_ostream &OS); | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 43 | Error writeSectionData(raw_ostream &OS); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 44 | Error writeLinkEditData(raw_ostream &OS); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 45 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 46 | void writeBindOpcodes(raw_ostream &OS, | 
| Chris Bieneman | 659b35a | 2016-05-26 20:50:05 +0000 | [diff] [blame] | 47 | std::vector<MachOYAML::BindOpcode> &BindOpcodes); | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 48 | // LinkEdit writers | 
|  | 49 | Error writeRebaseOpcodes(raw_ostream &OS); | 
|  | 50 | Error writeBasicBindOpcodes(raw_ostream &OS); | 
|  | 51 | Error writeWeakBindOpcodes(raw_ostream &OS); | 
|  | 52 | Error writeLazyBindOpcodes(raw_ostream &OS); | 
|  | 53 | Error writeNameList(raw_ostream &OS); | 
|  | 54 | Error writeStringTable(raw_ostream &OS); | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 55 | Error writeExportTrie(raw_ostream &OS); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 56 |  | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 57 | void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 58 | void ZeroToOffset(raw_ostream &OS, size_t offset); | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 59 |  | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 60 | MachOYAML::Object &Obj; | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 61 | bool is64Bit; | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 62 | uint64_t fileStart; | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 63 |  | 
| Chris Bieneman | 468208a | 2016-06-06 21:18:43 +0000 | [diff] [blame] | 64 | MachO::mach_header_64 Header; | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 65 | }; | 
|  | 66 |  | 
|  | 67 | Error MachOWriter::writeMachO(raw_ostream &OS) { | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 68 | fileStart = OS.tell(); | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 69 | if (auto Err = writeHeader(OS)) | 
|  | 70 | return Err; | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 71 | if (auto Err = writeLoadCommands(OS)) | 
|  | 72 | return Err; | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 73 | if (auto Err = writeSectionData(OS)) | 
|  | 74 | return Err; | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 75 | return Error::success(); | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | Error MachOWriter::writeHeader(raw_ostream &OS) { | 
|  | 79 | Header.magic = Obj.Header.magic; | 
|  | 80 | Header.cputype = Obj.Header.cputype; | 
|  | 81 | Header.cpusubtype = Obj.Header.cpusubtype; | 
|  | 82 | Header.filetype = Obj.Header.filetype; | 
|  | 83 | Header.ncmds = Obj.Header.ncmds; | 
|  | 84 | Header.sizeofcmds = Obj.Header.sizeofcmds; | 
|  | 85 | Header.flags = Obj.Header.flags; | 
| Chris Bieneman | 468208a | 2016-06-06 21:18:43 +0000 | [diff] [blame] | 86 | Header.reserved = Obj.Header.reserved; | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 87 |  | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 88 | if (Obj.IsLittleEndian != sys::IsLittleEndianHost) | 
|  | 89 | MachO::swapStruct(Header); | 
|  | 90 |  | 
| Chris Bieneman | 468208a | 2016-06-06 21:18:43 +0000 | [diff] [blame] | 91 | auto header_size = | 
|  | 92 | is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header); | 
|  | 93 | OS.write((const char *)&Header, header_size); | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 94 |  | 
|  | 95 | return Error::success(); | 
|  | 96 | } | 
|  | 97 |  | 
| Chris Bieneman | 2de17d4 | 2016-05-18 16:17:23 +0000 | [diff] [blame] | 98 | template <typename SectionType> | 
|  | 99 | SectionType constructSection(MachOYAML::Section Sec) { | 
|  | 100 | SectionType TempSec; | 
|  | 101 | memcpy(reinterpret_cast<void *>(&TempSec.sectname[0]), &Sec.sectname[0], 16); | 
|  | 102 | memcpy(reinterpret_cast<void *>(&TempSec.segname[0]), &Sec.segname[0], 16); | 
|  | 103 | TempSec.addr = Sec.addr; | 
|  | 104 | TempSec.size = Sec.size; | 
|  | 105 | TempSec.offset = Sec.offset; | 
|  | 106 | TempSec.align = Sec.align; | 
|  | 107 | TempSec.reloff = Sec.reloff; | 
|  | 108 | TempSec.nreloc = Sec.nreloc; | 
|  | 109 | TempSec.flags = Sec.flags; | 
|  | 110 | TempSec.reserved1 = Sec.reserved1; | 
|  | 111 | TempSec.reserved2 = Sec.reserved2; | 
|  | 112 | return TempSec; | 
|  | 113 | } | 
|  | 114 |  | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 115 | template <typename StructType> | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 116 | size_t writeLoadCommandData(MachOYAML::LoadCommand &LC, raw_ostream &OS, | 
|  | 117 | bool IsLittleEndian) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 118 | return 0; | 
|  | 119 | } | 
|  | 120 |  | 
|  | 121 | template <> | 
|  | 122 | size_t writeLoadCommandData<MachO::segment_command>(MachOYAML::LoadCommand &LC, | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 123 | raw_ostream &OS, | 
|  | 124 | bool IsLittleEndian) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 125 | size_t BytesWritten = 0; | 
| Benjamin Kramer | 4fed928 | 2016-05-27 12:30:51 +0000 | [diff] [blame] | 126 | for (const auto &Sec : LC.Sections) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 127 | auto TempSec = constructSection<MachO::section>(Sec); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 128 | if (IsLittleEndian != sys::IsLittleEndianHost) | 
|  | 129 | MachO::swapStruct(TempSec); | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 130 | OS.write(reinterpret_cast<const char *>(&(TempSec)), | 
|  | 131 | sizeof(MachO::section)); | 
|  | 132 | BytesWritten += sizeof(MachO::section); | 
|  | 133 | } | 
|  | 134 | return BytesWritten; | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | template <> | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 138 | size_t writeLoadCommandData<MachO::segment_command_64>( | 
|  | 139 | MachOYAML::LoadCommand &LC, raw_ostream &OS, bool IsLittleEndian) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 140 | size_t BytesWritten = 0; | 
| Benjamin Kramer | 4fed928 | 2016-05-27 12:30:51 +0000 | [diff] [blame] | 141 | for (const auto &Sec : LC.Sections) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 142 | auto TempSec = constructSection<MachO::section_64>(Sec); | 
|  | 143 | TempSec.reserved3 = Sec.reserved3; | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 144 | if (IsLittleEndian != sys::IsLittleEndianHost) | 
|  | 145 | MachO::swapStruct(TempSec); | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 146 | OS.write(reinterpret_cast<const char *>(&(TempSec)), | 
|  | 147 | sizeof(MachO::section_64)); | 
|  | 148 | BytesWritten += sizeof(MachO::section_64); | 
|  | 149 | } | 
|  | 150 | return BytesWritten; | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 | size_t writePayloadString(MachOYAML::LoadCommand &LC, raw_ostream &OS) { | 
|  | 154 | size_t BytesWritten = 0; | 
|  | 155 | if (!LC.PayloadString.empty()) { | 
|  | 156 | OS.write(LC.PayloadString.c_str(), LC.PayloadString.length()); | 
|  | 157 | BytesWritten = LC.PayloadString.length(); | 
|  | 158 | } | 
|  | 159 | return BytesWritten; | 
|  | 160 | } | 
|  | 161 |  | 
|  | 162 | template <> | 
|  | 163 | size_t writeLoadCommandData<MachO::dylib_command>(MachOYAML::LoadCommand &LC, | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 164 | raw_ostream &OS, | 
|  | 165 | bool IsLittleEndian) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 166 | return writePayloadString(LC, OS); | 
|  | 167 | } | 
|  | 168 |  | 
|  | 169 | template <> | 
|  | 170 | size_t writeLoadCommandData<MachO::dylinker_command>(MachOYAML::LoadCommand &LC, | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 171 | raw_ostream &OS, | 
|  | 172 | bool IsLittleEndian) { | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 173 | return writePayloadString(LC, OS); | 
|  | 174 | } | 
|  | 175 |  | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 176 | template <> | 
|  | 177 | size_t writeLoadCommandData<MachO::rpath_command>(MachOYAML::LoadCommand &LC, | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 178 | raw_ostream &OS, | 
|  | 179 | bool IsLittleEndian) { | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 180 | return writePayloadString(LC, OS); | 
|  | 181 | } | 
|  | 182 |  | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 183 | void ZeroFillBytes(raw_ostream &OS, size_t Size) { | 
|  | 184 | std::vector<uint8_t> FillData; | 
|  | 185 | FillData.insert(FillData.begin(), Size, 0); | 
|  | 186 | OS.write(reinterpret_cast<char *>(FillData.data()), Size); | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | void Fill(raw_ostream &OS, size_t Size, uint32_t Data) { | 
|  | 190 | std::vector<uint32_t> FillData; | 
|  | 191 | FillData.insert(FillData.begin(), (Size / 4) + 1, Data); | 
|  | 192 | OS.write(reinterpret_cast<char *>(FillData.data()), Size); | 
|  | 193 | } | 
|  | 194 |  | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 195 | void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) { | 
|  | 196 | auto currOffset = OS.tell() - fileStart; | 
|  | 197 | if (currOffset < Offset) | 
|  | 198 | ZeroFillBytes(OS, Offset - currOffset); | 
|  | 199 | } | 
|  | 200 |  | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 201 | Error MachOWriter::writeLoadCommands(raw_ostream &OS) { | 
|  | 202 | for (auto &LC : Obj.LoadCommands) { | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 203 | size_t BytesWritten = 0; | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 204 | llvm::MachO::macho_load_command Data = LC.Data; | 
|  | 205 |  | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 206 | #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct)                         \ | 
|  | 207 | case MachO::LCName:                                                          \ | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 208 | if (Obj.IsLittleEndian != sys::IsLittleEndianHost)                         \ | 
|  | 209 | MachO::swapStruct(Data.LCStruct##_data);                                 \ | 
|  | 210 | OS.write(reinterpret_cast<const char *>(&(Data.LCStruct##_data)),          \ | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 211 | sizeof(MachO::LCStruct));                                         \ | 
|  | 212 | BytesWritten = sizeof(MachO::LCStruct);                                    \ | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 213 | BytesWritten +=                                                            \ | 
|  | 214 | writeLoadCommandData<MachO::LCStruct>(LC, OS, Obj.IsLittleEndian);     \ | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 215 | break; | 
|  | 216 |  | 
|  | 217 | switch (LC.Data.load_command_data.cmd) { | 
|  | 218 | default: | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 219 | if (Obj.IsLittleEndian != sys::IsLittleEndianHost) | 
|  | 220 | MachO::swapStruct(Data.load_command_data); | 
|  | 221 | OS.write(reinterpret_cast<const char *>(&(Data.load_command_data)), | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 222 | sizeof(MachO::load_command)); | 
|  | 223 | BytesWritten = sizeof(MachO::load_command); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 224 | BytesWritten += | 
|  | 225 | writeLoadCommandData<MachO::load_command>(LC, OS, Obj.IsLittleEndian); | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 226 | break; | 
|  | 227 | #include "llvm/Support/MachO.def" | 
|  | 228 | } | 
|  | 229 |  | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 230 | if (LC.PayloadBytes.size() > 0) { | 
|  | 231 | OS.write(reinterpret_cast<const char *>(LC.PayloadBytes.data()), | 
|  | 232 | LC.PayloadBytes.size()); | 
|  | 233 | BytesWritten += LC.PayloadBytes.size(); | 
| Chris Bieneman | 2de17d4 | 2016-05-18 16:17:23 +0000 | [diff] [blame] | 234 | } | 
|  | 235 |  | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 236 | if (LC.ZeroPadBytes > 0) { | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 237 | ZeroFillBytes(OS, LC.ZeroPadBytes); | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 238 | BytesWritten += LC.ZeroPadBytes; | 
|  | 239 | } | 
|  | 240 |  | 
| Chris Bieneman | 1abf005 | 2016-05-19 23:26:31 +0000 | [diff] [blame] | 241 | // Fill remaining bytes with 0. This will only get hit in partially | 
|  | 242 | // specified test cases. | 
| Chris Bieneman | 9f243e9 | 2016-05-19 20:54:43 +0000 | [diff] [blame] | 243 | auto BytesRemaining = LC.Data.load_command_data.cmdsize - BytesWritten; | 
| Chris Bieneman | 3f2eb83 | 2016-05-17 19:44:06 +0000 | [diff] [blame] | 244 | if (BytesRemaining > 0) { | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 245 | ZeroFillBytes(OS, BytesRemaining); | 
|  | 246 | } | 
|  | 247 | } | 
|  | 248 | return Error::success(); | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | Error MachOWriter::writeSectionData(raw_ostream &OS) { | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 252 | bool FoundLinkEditSeg = false; | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 253 | for (auto &LC : Obj.LoadCommands) { | 
|  | 254 | switch (LC.Data.load_command_data.cmd) { | 
|  | 255 | case MachO::LC_SEGMENT: | 
|  | 256 | case MachO::LC_SEGMENT_64: | 
|  | 257 | uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff | 
|  | 258 | : LC.Data.segment_command_data.fileoff; | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 259 | if (0 == strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) { | 
|  | 260 | FoundLinkEditSeg = true; | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 261 | if (auto Err = writeLinkEditData(OS)) | 
|  | 262 | return Err; | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 263 | } | 
|  | 264 | for (auto &Sec : LC.Sections) { | 
|  | 265 | ZeroToOffset(OS, Sec.offset); | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 266 | // Zero Fill any data between the end of the last thing we wrote and the | 
|  | 267 | // start of this section. | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 268 | assert((OS.tell() - fileStart <= Sec.offset || | 
|  | 269 | Sec.offset == (uint32_t)0) && | 
|  | 270 | "Wrote too much data somewhere, section offsets don't line up."); | 
|  | 271 | if (0 == strncmp(&Sec.segname[0], "__DWARF", 16)) { | 
|  | 272 | if (0 == strncmp(&Sec.sectname[0], "__debug_str", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 273 | DWARFYAML::EmitDebugStr(OS, Obj.DWARF); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 274 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_abbrev", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 275 | DWARFYAML::EmitDebugAbbrev(OS, Obj.DWARF); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 276 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_aranges", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 277 | DWARFYAML::EmitDebugAranges(OS, Obj.DWARF); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 278 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_pubnames", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 279 | DWARFYAML::EmitPubSection(OS, Obj.DWARF.PubNames, | 
|  | 280 | Obj.IsLittleEndian); | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 281 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_pubtypes", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 282 | DWARFYAML::EmitPubSection(OS, Obj.DWARF.PubTypes, | 
|  | 283 | Obj.IsLittleEndian); | 
| Chris Bieneman | e0e451d | 2016-12-22 22:44:27 +0000 | [diff] [blame] | 284 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_info", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 285 | DWARFYAML::EmitDebugInfo(OS, Obj.DWARF); | 
| Chris Bieneman | 1b7200d | 2017-01-10 06:22:49 +0000 | [diff] [blame] | 286 | } else if (0 == strncmp(&Sec.sectname[0], "__debug_line", 16)) { | 
| Chris Bieneman | 07088c1 | 2017-01-12 21:35:21 +0000 | [diff] [blame^] | 287 | DWARFYAML::EmitDebugLine(OS, Obj.DWARF); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 288 | } | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 289 | } else { | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 290 | // Fills section data with 0xDEADBEEF | 
|  | 291 | Fill(OS, Sec.size, 0xDEADBEEFu); | 
|  | 292 | } | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 293 | } | 
|  | 294 | uint64_t segSize = is64Bit ? LC.Data.segment_command_64_data.filesize | 
|  | 295 | : LC.Data.segment_command_data.filesize; | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 296 | ZeroToOffset(OS, segOff + segSize); | 
| Chris Bieneman | e18fee2 | 2016-05-20 22:31:50 +0000 | [diff] [blame] | 297 | break; | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 298 | } | 
|  | 299 | } | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 300 | // Old PPC Object Files didn't have __LINKEDIT segments, the data was just | 
|  | 301 | // stuck at the end of the file. | 
|  | 302 | if (!FoundLinkEditSeg) { | 
|  | 303 | if (auto Err = writeLinkEditData(OS)) | 
|  | 304 | return Err; | 
|  | 305 | } | 
| Chris Bieneman | 8b5906e | 2016-05-13 17:41:41 +0000 | [diff] [blame] | 306 | return Error::success(); | 
|  | 307 | } | 
|  | 308 |  | 
| Chris Bieneman | 659b35a | 2016-05-26 20:50:05 +0000 | [diff] [blame] | 309 | void MachOWriter::writeBindOpcodes( | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 310 | raw_ostream &OS, std::vector<MachOYAML::BindOpcode> &BindOpcodes) { | 
| Chris Bieneman | 659b35a | 2016-05-26 20:50:05 +0000 | [diff] [blame] | 311 |  | 
|  | 312 | for (auto Opcode : BindOpcodes) { | 
|  | 313 | uint8_t OpByte = Opcode.Opcode | Opcode.Imm; | 
|  | 314 | OS.write(reinterpret_cast<char *>(&OpByte), 1); | 
|  | 315 | for (auto Data : Opcode.ULEBExtraData) { | 
|  | 316 | encodeULEB128(Data, OS); | 
|  | 317 | } | 
|  | 318 | for (auto Data : Opcode.SLEBExtraData) { | 
|  | 319 | encodeSLEB128(Data, OS); | 
|  | 320 | } | 
|  | 321 | if (!Opcode.Symbol.empty()) { | 
|  | 322 | OS.write(Opcode.Symbol.data(), Opcode.Symbol.size()); | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 323 | OS.write('\0'); | 
| Chris Bieneman | 659b35a | 2016-05-26 20:50:05 +0000 | [diff] [blame] | 324 | } | 
|  | 325 | } | 
|  | 326 | } | 
|  | 327 |  | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 328 | void MachOWriter::dumpExportEntry(raw_ostream &OS, | 
|  | 329 | MachOYAML::ExportEntry &Entry) { | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 330 | encodeSLEB128(Entry.TerminalSize, OS); | 
|  | 331 | if (Entry.TerminalSize > 0) { | 
|  | 332 | encodeSLEB128(Entry.Flags, OS); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 333 | if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 334 | encodeSLEB128(Entry.Other, OS); | 
|  | 335 | OS << Entry.ImportName; | 
|  | 336 | OS.write('\0'); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 337 | } else { | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 338 | encodeSLEB128(Entry.Address, OS); | 
|  | 339 | if (Entry.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) | 
|  | 340 | encodeSLEB128(Entry.Other, OS); | 
|  | 341 | } | 
|  | 342 | } | 
|  | 343 | OS.write(static_cast<uint8_t>(Entry.Children.size())); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 344 | for (auto EE : Entry.Children) { | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 345 | OS << EE.Name; | 
|  | 346 | OS.write('\0'); | 
|  | 347 | encodeSLEB128(EE.NodeOffset, OS); | 
|  | 348 | } | 
|  | 349 | for (auto EE : Entry.Children) | 
|  | 350 | dumpExportEntry(OS, EE); | 
|  | 351 | } | 
|  | 352 |  | 
|  | 353 | Error MachOWriter::writeExportTrie(raw_ostream &OS) { | 
|  | 354 | dumpExportEntry(OS, Obj.LinkEdit.ExportTrie); | 
|  | 355 | return Error::success(); | 
|  | 356 | } | 
|  | 357 |  | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 358 | template <typename NListType> | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 359 | void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS, | 
|  | 360 | bool IsLittleEndian) { | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 361 | NListType ListEntry; | 
|  | 362 | ListEntry.n_strx = NLE.n_strx; | 
|  | 363 | ListEntry.n_type = NLE.n_type; | 
|  | 364 | ListEntry.n_sect = NLE.n_sect; | 
|  | 365 | ListEntry.n_desc = NLE.n_desc; | 
|  | 366 | ListEntry.n_value = NLE.n_value; | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 367 |  | 
| Chris Bieneman | e477fb9 | 2016-12-22 22:16:04 +0000 | [diff] [blame] | 368 | if (IsLittleEndian != sys::IsLittleEndianHost) | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 369 | MachO::swapStruct(ListEntry); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 370 | OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType)); | 
|  | 371 | } | 
|  | 372 |  | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 373 | Error MachOWriter::writeLinkEditData(raw_ostream &OS) { | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 374 | typedef Error (MachOWriter::*writeHandler)(raw_ostream &); | 
|  | 375 | typedef std::pair<uint64_t, writeHandler> writeOperation; | 
|  | 376 | std::vector<writeOperation> WriteQueue; | 
|  | 377 |  | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 378 | MachO::dyld_info_command *DyldInfoOnlyCmd = 0; | 
|  | 379 | MachO::symtab_command *SymtabCmd = 0; | 
|  | 380 | for (auto &LC : Obj.LoadCommands) { | 
|  | 381 | switch (LC.Data.load_command_data.cmd) { | 
|  | 382 | case MachO::LC_SYMTAB: | 
|  | 383 | SymtabCmd = &LC.Data.symtab_command_data; | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 384 | WriteQueue.push_back( | 
|  | 385 | std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList)); | 
|  | 386 | WriteQueue.push_back( | 
|  | 387 | std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable)); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 388 | break; | 
|  | 389 | case MachO::LC_DYLD_INFO_ONLY: | 
|  | 390 | DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data; | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 391 | WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off, | 
|  | 392 | &MachOWriter::writeRebaseOpcodes)); | 
|  | 393 | WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off, | 
|  | 394 | &MachOWriter::writeBasicBindOpcodes)); | 
|  | 395 | WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off, | 
|  | 396 | &MachOWriter::writeWeakBindOpcodes)); | 
|  | 397 | WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off, | 
|  | 398 | &MachOWriter::writeLazyBindOpcodes)); | 
|  | 399 | WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off, | 
|  | 400 | &MachOWriter::writeExportTrie)); | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 401 | break; | 
|  | 402 | } | 
|  | 403 | } | 
|  | 404 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 405 | std::sort(WriteQueue.begin(), WriteQueue.end(), | 
|  | 406 | [](const writeOperation &a, const writeOperation &b) { | 
|  | 407 | return a.first < b.first; | 
|  | 408 | }); | 
|  | 409 |  | 
|  | 410 | for (auto writeOp : WriteQueue) { | 
|  | 411 | ZeroToOffset(OS, writeOp.first); | 
|  | 412 | if (auto Err = (this->*writeOp.second)(OS)) | 
|  | 413 | return Err; | 
|  | 414 | } | 
|  | 415 |  | 
|  | 416 | return Error::success(); | 
|  | 417 | } | 
|  | 418 |  | 
|  | 419 | Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) { | 
|  | 420 | MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit; | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 421 |  | 
|  | 422 | for (auto Opcode : LinkEdit.RebaseOpcodes) { | 
|  | 423 | uint8_t OpByte = Opcode.Opcode | Opcode.Imm; | 
|  | 424 | OS.write(reinterpret_cast<char *>(&OpByte), 1); | 
|  | 425 | for (auto Data : Opcode.ExtraData) { | 
|  | 426 | encodeULEB128(Data, OS); | 
|  | 427 | } | 
|  | 428 | } | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 429 | return Error::success(); | 
|  | 430 | } | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 431 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 432 | Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) { | 
|  | 433 | writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes); | 
|  | 434 | return Error::success(); | 
|  | 435 | } | 
| Chris Bieneman | 524243d | 2016-05-26 20:06:14 +0000 | [diff] [blame] | 436 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 437 | Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) { | 
|  | 438 | writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes); | 
|  | 439 | return Error::success(); | 
|  | 440 | } | 
| Chris Bieneman | 6852775 | 2016-05-31 17:26:36 +0000 | [diff] [blame] | 441 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 442 | Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) { | 
|  | 443 | writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes); | 
|  | 444 | return Error::success(); | 
|  | 445 | } | 
|  | 446 |  | 
|  | 447 | Error MachOWriter::writeNameList(raw_ostream &OS) { | 
|  | 448 | for (auto NLE : Obj.LinkEdit.NameList) { | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 449 | if (is64Bit) | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 450 | writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 451 | else | 
| Chris Bieneman | 55de3a2 | 2016-12-22 21:58:03 +0000 | [diff] [blame] | 452 | writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian); | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 453 | } | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 454 | return Error::success(); | 
|  | 455 | } | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 456 |  | 
| Chris Bieneman | 4c42377 | 2016-06-03 16:58:05 +0000 | [diff] [blame] | 457 | Error MachOWriter::writeStringTable(raw_ostream &OS) { | 
|  | 458 | for (auto Str : Obj.LinkEdit.StringTable) { | 
| Chris Bieneman | 07bb3c8 | 2016-06-02 22:54:06 +0000 | [diff] [blame] | 459 | OS.write(Str.data(), Str.size()); | 
|  | 460 | OS.write('\0'); | 
|  | 461 | } | 
| Chris Bieneman | e8e7555 | 2016-05-25 17:09:07 +0000 | [diff] [blame] | 462 | return Error::success(); | 
|  | 463 | } | 
|  | 464 |  | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 465 | class UniversalWriter { | 
|  | 466 | public: | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 467 | UniversalWriter(yaml::YamlObjectFile &ObjectFile) | 
|  | 468 | : ObjectFile(ObjectFile), fileStart(0) {} | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 469 |  | 
|  | 470 | Error writeMachO(raw_ostream &OS); | 
|  | 471 |  | 
|  | 472 | private: | 
|  | 473 | Error writeFatHeader(raw_ostream &OS); | 
|  | 474 | Error writeFatArchs(raw_ostream &OS); | 
|  | 475 |  | 
|  | 476 | void ZeroToOffset(raw_ostream &OS, size_t offset); | 
|  | 477 |  | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 478 | yaml::YamlObjectFile &ObjectFile; | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 479 | uint64_t fileStart; | 
|  | 480 | }; | 
|  | 481 |  | 
|  | 482 | Error UniversalWriter::writeMachO(raw_ostream &OS) { | 
|  | 483 | fileStart = OS.tell(); | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 484 | if (ObjectFile.MachO) { | 
|  | 485 | MachOWriter Writer(*ObjectFile.MachO); | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 486 | return Writer.writeMachO(OS); | 
|  | 487 | } | 
|  | 488 | if (auto Err = writeFatHeader(OS)) | 
|  | 489 | return Err; | 
|  | 490 | if (auto Err = writeFatArchs(OS)) | 
|  | 491 | return Err; | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 492 | auto &FatFile = *ObjectFile.FatMachO; | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 493 | assert(FatFile.FatArchs.size() == FatFile.Slices.size()); | 
|  | 494 | for (size_t i = 0; i < FatFile.Slices.size(); i++) { | 
|  | 495 | ZeroToOffset(OS, FatFile.FatArchs[i].offset); | 
|  | 496 | MachOWriter Writer(FatFile.Slices[i]); | 
|  | 497 | if (auto Err = Writer.writeMachO(OS)) | 
|  | 498 | return Err; | 
|  | 499 | auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size; | 
|  | 500 | ZeroToOffset(OS, SliceEnd); | 
|  | 501 | } | 
|  | 502 | return Error::success(); | 
|  | 503 | } | 
|  | 504 |  | 
|  | 505 | Error UniversalWriter::writeFatHeader(raw_ostream &OS) { | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 506 | auto &FatFile = *ObjectFile.FatMachO; | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 507 | MachO::fat_header header; | 
|  | 508 | header.magic = FatFile.Header.magic; | 
|  | 509 | header.nfat_arch = FatFile.Header.nfat_arch; | 
|  | 510 | if (sys::IsLittleEndianHost) | 
|  | 511 | swapStruct(header); | 
|  | 512 | OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header)); | 
|  | 513 | return Error::success(); | 
|  | 514 | } | 
|  | 515 |  | 
|  | 516 | template <typename FatArchType> | 
|  | 517 | FatArchType constructFatArch(MachOYAML::FatArch &Arch) { | 
|  | 518 | FatArchType FatArch; | 
|  | 519 | FatArch.cputype = Arch.cputype; | 
|  | 520 | FatArch.cpusubtype = Arch.cpusubtype; | 
|  | 521 | FatArch.offset = Arch.offset; | 
|  | 522 | FatArch.size = Arch.size; | 
|  | 523 | FatArch.align = Arch.align; | 
|  | 524 | return FatArch; | 
|  | 525 | } | 
|  | 526 |  | 
|  | 527 | template <typename StructType> | 
|  | 528 | void writeFatArch(MachOYAML::FatArch &LC, raw_ostream &OS) {} | 
|  | 529 |  | 
|  | 530 | template <> | 
|  | 531 | void writeFatArch<MachO::fat_arch>(MachOYAML::FatArch &Arch, raw_ostream &OS) { | 
|  | 532 | auto FatArch = constructFatArch<MachO::fat_arch>(Arch); | 
|  | 533 | if (sys::IsLittleEndianHost) | 
|  | 534 | swapStruct(FatArch); | 
|  | 535 | OS.write(reinterpret_cast<const char *>(&FatArch), sizeof(MachO::fat_arch)); | 
|  | 536 | } | 
|  | 537 |  | 
|  | 538 | template <> | 
|  | 539 | void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch, | 
|  | 540 | raw_ostream &OS) { | 
|  | 541 | auto FatArch = constructFatArch<MachO::fat_arch_64>(Arch); | 
|  | 542 | FatArch.reserved = Arch.reserved; | 
|  | 543 | if (sys::IsLittleEndianHost) | 
|  | 544 | swapStruct(FatArch); | 
|  | 545 | OS.write(reinterpret_cast<const char *>(&FatArch), | 
|  | 546 | sizeof(MachO::fat_arch_64)); | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | Error UniversalWriter::writeFatArchs(raw_ostream &OS) { | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 550 | auto &FatFile = *ObjectFile.FatMachO; | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 551 | bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64; | 
|  | 552 | for (auto Arch : FatFile.FatArchs) { | 
|  | 553 | if (is64Bit) | 
|  | 554 | writeFatArch<MachO::fat_arch_64>(Arch, OS); | 
|  | 555 | else | 
|  | 556 | writeFatArch<MachO::fat_arch>(Arch, OS); | 
|  | 557 | } | 
|  | 558 |  | 
|  | 559 | return Error::success(); | 
|  | 560 | } | 
|  | 561 |  | 
|  | 562 | void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) { | 
|  | 563 | auto currOffset = OS.tell() - fileStart; | 
|  | 564 | if (currOffset < Offset) | 
|  | 565 | ZeroFillBytes(OS, Offset - currOffset); | 
|  | 566 | } | 
|  | 567 |  | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 568 | } // end anonymous namespace | 
|  | 569 |  | 
| Chris Bieneman | 8ff0c11 | 2016-06-27 19:53:53 +0000 | [diff] [blame] | 570 | int yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) { | 
| Chris Bieneman | 93e7119 | 2016-06-24 20:42:28 +0000 | [diff] [blame] | 571 | UniversalWriter Writer(Doc); | 
| Chris Bieneman | a23b26f | 2016-05-12 17:44:48 +0000 | [diff] [blame] | 572 | if (auto Err = Writer.writeMachO(Out)) { | 
|  | 573 | errs() << toString(std::move(Err)); | 
|  | 574 | return 1; | 
|  | 575 | } | 
|  | 576 | return 0; | 
| Chris Bieneman | b83c187 | 2016-05-11 22:07:48 +0000 | [diff] [blame] | 577 | } |