llvm.org GIT mirror llvm / b7daa17
[yaml2obj] Sort MachO LinkEdit write operations based on offset This re-applies r271611, and hopefully the bots won't break this time. Although ld64 always outputs linkedit data in the same order, it isn't actually required to. This change makes yaml2obj resilient if the offsets are in arbitrary order. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271687 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Bieneman 3 years ago
2 changed file(s) with 334 addition(s) and 30 deletion(s). Raw diff Collapse all Expand all
0 # RUN: yaml2obj -format=macho %s | obj2yaml | FileCheck %s
1
2 --- !mach-o
3 FileHeader:
4 magic: 0xFEEDFACF
5 cputype: 0x01000007
6 cpusubtype: 0x80000003
7 filetype: 0x00000002
8 ncmds: 16
9 sizeofcmds: 1408
10 flags: 0x00218085
11 reserved: 0x00000000
12 LoadCommands:
13 - cmd: LC_SEGMENT_64
14 cmdsize: 72
15 segname: __PAGEZERO
16 vmaddr: 0
17 vmsize: 4294967296
18 fileoff: 0
19 filesize: 0
20 maxprot: 0
21 initprot: 0
22 nsects: 0
23 flags: 0
24 - cmd: LC_SEGMENT_64
25 cmdsize: 552
26 segname: __TEXT
27 vmaddr: 4294967296
28 vmsize: 8192
29 fileoff: 0
30 filesize: 8192
31 maxprot: 7
32 initprot: 5
33 nsects: 6
34 flags: 0
35 - cmd: LC_SEGMENT_64
36 cmdsize: 312
37 segname: __DATA
38 vmaddr: 4294975488
39 vmsize: 4096
40 fileoff: 8192
41 filesize: 4096
42 maxprot: 7
43 initprot: 3
44 nsects: 3
45 flags: 0
46 - cmd: LC_SEGMENT_64
47 cmdsize: 72
48 segname: __LINKEDIT
49 vmaddr: 4294979584
50 vmsize: 4096
51 fileoff: 12288
52 filesize: 2508
53 maxprot: 7
54 initprot: 1
55 nsects: 0
56 flags: 0
57 - cmd: LC_DYLD_INFO_ONLY
58 cmdsize: 48
59 rebase_off: 12384
60 rebase_size: 8
61 bind_off: 12288
62 bind_size: 96
63 weak_bind_off: 0
64 weak_bind_size: 0
65 lazy_bind_off: 12392
66 lazy_bind_size: 624
67 export_off: 13016
68 export_size: 48
69 - cmd: LC_SYMTAB
70 cmdsize: 24
71 symoff: 13080
72 nsyms: 30
73 stroff: 13700
74 strsize: 1096
75 - cmd: LC_DYSYMTAB
76 cmdsize: 80
77 ilocalsym: 0
78 nlocalsym: 9
79 iextdefsym: 9
80 nextdefsym: 2
81 iundefsym: 11
82 nundefsym: 19
83 tocoff: 0
84 ntoc: 0
85 modtaboff: 0
86 nmodtab: 0
87 extrefsymoff: 0
88 nextrefsyms: 0
89 indirectsymoff: 13560
90 nindirectsyms: 35
91 extreloff: 0
92 nextrel: 0
93 locreloff: 0
94 nlocrel: 0
95 - cmd: LC_LOAD_DYLINKER
96 cmdsize: 32
97 name: 12
98 PayloadString: /usr/lib/dyld
99 ZeroPadBytes: 7
100 - cmd: LC_UUID
101 cmdsize: 24
102 uuid: 461A1B28-822F-3F38-B670-645419E636F5
103 - cmd: LC_VERSION_MIN_MACOSX
104 cmdsize: 16
105 version: 658176
106 sdk: 658176
107 - cmd: LC_SOURCE_VERSION
108 cmdsize: 16
109 version: 0
110 - cmd: LC_MAIN
111 cmdsize: 24
112 entryoff: 4448
113 stacksize: 0
114 - cmd: LC_LOAD_DYLIB
115 cmdsize: 48
116 dylib:
117 name: 24
118 timestamp: 2
119 current_version: 7864576
120 compatibility_version: 65536
121 PayloadString: '/usr/lib/libc++.1.dylib'
122 ZeroPadBytes: 1
123 - cmd: LC_LOAD_DYLIB
124 cmdsize: 56
125 dylib:
126 name: 24
127 timestamp: 2
128 current_version: 80349697
129 compatibility_version: 65536
130 PayloadString: /usr/lib/libSystem.B.dylib
131 ZeroPadBytes: 6
132 - cmd: LC_FUNCTION_STARTS
133 cmdsize: 16
134 dataoff: 13064
135 datasize: 16
136 - cmd: LC_DATA_IN_CODE
137 cmdsize: 16
138 dataoff: 13080
139 datasize: 0
140 LinkEditData:
141 RebaseOpcodes:
142 - Opcode: REBASE_OPCODE_SET_TYPE_IMM
143 Imm: 1
144 - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
145 Imm: 2
146 ExtraData:
147 - 0x0000000000000028
148 - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
149 Imm: 0
150 ExtraData:
151 - 0x000000000000000F
152 - Opcode: REBASE_OPCODE_DONE
153 Imm: 0
154 BindOpcodes:
155 - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
156 Imm: 1
157 Symbol: ''
158 - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
159 Imm: 0
160 Symbol: __ZNSt3__14coutE
161 - Opcode: BIND_OPCODE_SET_TYPE_IMM
162 Imm: 1
163 Symbol: ''
164 - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
165 Imm: 2
166 ULEBExtraData:
167 - 0x0000000000000000
168 Symbol: ''
169 - Opcode: BIND_OPCODE_DO_BIND
170 Imm: 0
171 Symbol: ''
172 - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
173 Imm: 0
174 Symbol: __ZNSt3__15ctypeIcE2idE
175 - Opcode: BIND_OPCODE_DO_BIND
176 Imm: 0
177 Symbol: ''
178 - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
179 Imm: 0
180 Symbol: ___gxx_personality_v0
181 - Opcode: BIND_OPCODE_DO_BIND
182 Imm: 0
183 Symbol: ''
184 - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
185 Imm: 2
186 Symbol: ''
187 - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
188 Imm: 0
189 Symbol: dyld_stub_binder
190 - Opcode: BIND_OPCODE_DO_BIND
191 Imm: 0
192 Symbol: ''
193 - Opcode: BIND_OPCODE_DONE
194 Imm: 0
195 Symbol: ''
196 ...
197
198 #CHECK: - cmd: LC_DYLD_INFO_ONLY
199 #CHECK: cmdsize: 48
200 #CHECK: rebase_off: 12384
201 #CHECK: rebase_size: 8
202 #CHECK: bind_off: 12288
203 #CHECK: bind_size: 96
204 #CHECK: weak_bind_off: 0
205 #CHECK: weak_bind_size: 0
206 #CHECK: lazy_bind_off: 12392
207 #CHECK: lazy_bind_size: 624
208 #CHECK: export_off: 13016
209 #CHECK: export_size: 48
210 #CHECK: LinkEditData:
211 #CHECK: RebaseOpcodes:
212 #CHECK: - Opcode: REBASE_OPCODE_SET_TYPE_IMM
213 #CHECK: Imm: 1
214 #CHECK: - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
215 #CHECK: Imm: 2
216 #CHECK: ExtraData:
217 #CHECK: - 0x0000000000000028
218 #CHECK: - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES
219 #CHECK: Imm: 0
220 #CHECK: ExtraData:
221 #CHECK: - 0x000000000000000F
222 #CHECK: - Opcode: REBASE_OPCODE_DONE
223 #CHECK: Imm: 0
224 #CHECK: BindOpcodes:
225 #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
226 #CHECK: Imm: 1
227 #CHECK: Symbol: ''
228 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
229 #CHECK: Imm: 0
230 #CHECK: Symbol: __ZNSt3__14coutE
231 #CHECK: - Opcode: BIND_OPCODE_SET_TYPE_IMM
232 #CHECK: Imm: 1
233 #CHECK: Symbol: ''
234 #CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
235 #CHECK: Imm: 2
236 #CHECK: ULEBExtraData:
237 #CHECK: - 0x0000000000000000
238 #CHECK: Symbol: ''
239 #CHECK: - Opcode: BIND_OPCODE_DO_BIND
240 #CHECK: Imm: 0
241 #CHECK: Symbol: ''
242 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
243 #CHECK: Imm: 0
244 #CHECK: Symbol: __ZNSt3__15ctypeIcE2idE
245 #CHECK: - Opcode: BIND_OPCODE_DO_BIND
246 #CHECK: Imm: 0
247 #CHECK: Symbol: ''
248 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
249 #CHECK: Imm: 0
250 #CHECK: Symbol: ___gxx_personality_v0
251 #CHECK: - Opcode: BIND_OPCODE_DO_BIND
252 #CHECK: Imm: 0
253 #CHECK: Symbol: ''
254 #CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
255 #CHECK: Imm: 2
256 #CHECK: Symbol: ''
257 #CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
258 #CHECK: Imm: 0
259 #CHECK: Symbol: dyld_stub_binder
260 #CHECK: - Opcode: BIND_OPCODE_DO_BIND
261 #CHECK: Imm: 0
262 #CHECK: Symbol: ''
263 #CHECK: - Opcode: BIND_OPCODE_DONE
264 #CHECK: Imm: 0
265 #CHECK: Symbol: ''
4545 Error writeLoadCommands(raw_ostream &OS);
4646 Error writeSectionData(raw_ostream &OS);
4747 Error writeLinkEditData(raw_ostream &OS);
48 void writeBindOpcodes(raw_ostream &OS, uint64_t offset,
48 void writeBindOpcodes(raw_ostream &OS,
4949 std::vector &BindOpcodes);
50 // LinkEdit writers
51 Error writeRebaseOpcodes(raw_ostream &OS);
52 Error writeBasicBindOpcodes(raw_ostream &OS);
53 Error writeWeakBindOpcodes(raw_ostream &OS);
54 Error writeLazyBindOpcodes(raw_ostream &OS);
55 Error writeNameList(raw_ostream &OS);
56 Error writeStringTable(raw_ostream &OS);
5057 Error writeExportTrie(raw_ostream &OS);
5158
5259 void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
274281 }
275282
276283 void MachOWriter::writeBindOpcodes(
277 raw_ostream &OS, uint64_t offset,
278 std::vector &BindOpcodes) {
279 ZeroToOffset(OS, offset);
284 raw_ostream &OS, std::vector &BindOpcodes) {
280285
281286 for (auto Opcode : BindOpcodes) {
282287 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
336341 }
337342
338343 Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
339 MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
344 typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
345 typedef std::pair writeOperation;
346 std::vector WriteQueue;
347
340348 MachO::dyld_info_command *DyldInfoOnlyCmd = 0;
341349 MachO::symtab_command *SymtabCmd = 0;
342350 for (auto &LC : Obj.LoadCommands) {
343351 switch (LC.Data.load_command_data.cmd) {
344352 case MachO::LC_SYMTAB:
345353 SymtabCmd = &LC.Data.symtab_command_data;
354 WriteQueue.push_back(
355 std::make_pair(SymtabCmd->symoff, &MachOWriter::writeNameList));
356 WriteQueue.push_back(
357 std::make_pair(SymtabCmd->stroff, &MachOWriter::writeStringTable));
346358 break;
347359 case MachO::LC_DYLD_INFO_ONLY:
348360 DyldInfoOnlyCmd = &LC.Data.dyld_info_command_data;
361 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->rebase_off,
362 &MachOWriter::writeRebaseOpcodes));
363 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->bind_off,
364 &MachOWriter::writeBasicBindOpcodes));
365 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->weak_bind_off,
366 &MachOWriter::writeWeakBindOpcodes));
367 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->lazy_bind_off,
368 &MachOWriter::writeLazyBindOpcodes));
369 WriteQueue.push_back(std::make_pair(DyldInfoOnlyCmd->export_off,
370 &MachOWriter::writeExportTrie));
349371 break;
350372 }
351373 }
352374
353 ZeroToOffset(OS, DyldInfoOnlyCmd->rebase_off);
375 std::sort(WriteQueue.begin(), WriteQueue.end(),
376 [](const writeOperation &a, const writeOperation &b) {
377 return a.first < b.first;
378 });
379
380 for (auto writeOp : WriteQueue) {
381 ZeroToOffset(OS, writeOp.first);
382 if (auto Err = (this->*writeOp.second)(OS))
383 return Err;
384 }
385
386 return Error::success();
387 }
388
389 Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
390 MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
354391
355392 for (auto Opcode : LinkEdit.RebaseOpcodes) {
356393 uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
359396 encodeULEB128(Data, OS);
360397 }
361398 }
362
363 writeBindOpcodes(OS, DyldInfoOnlyCmd->bind_off, LinkEdit.BindOpcodes);
364 writeBindOpcodes(OS, DyldInfoOnlyCmd->weak_bind_off,
365 LinkEdit.WeakBindOpcodes);
366 writeBindOpcodes(OS, DyldInfoOnlyCmd->lazy_bind_off,
367 LinkEdit.LazyBindOpcodes);
368
369 ZeroToOffset(OS, DyldInfoOnlyCmd->export_off);
370 if (auto Err = writeExportTrie(OS))
371 return Err;
372
373 ZeroToOffset(OS, SymtabCmd->symoff);
374
375 for (auto NLE : LinkEdit.NameList) {
399 return Error::success();
400 }
401
402 Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
403 writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
404 return Error::success();
405 }
406
407 Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
408 writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
409 return Error::success();
410 }
411
412 Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
413 writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
414 return Error::success();
415 }
416
417 Error MachOWriter::writeNameList(raw_ostream &OS) {
418 for (auto NLE : Obj.LinkEdit.NameList) {
376419 if (is64Bit)
377420 writeNListEntry(NLE, OS);
378421 else
379422 writeNListEntry(NLE, OS);
380423 }
381
382 auto currOffset = OS.tell() - fileStart;
383 if (currOffset < SymtabCmd->stroff)
384 Fill(OS, SymtabCmd->stroff - currOffset, 0xDEADBEEFu);
385
386 for (auto Str : LinkEdit.StringTable) {
424 return Error::success();
425 }
426
427 Error MachOWriter::writeStringTable(raw_ostream &OS) {
428 for (auto Str : Obj.LinkEdit.StringTable) {
387429 OS.write(Str.data(), Str.size());
388430 OS.write('\0');
389431 }
390
391 // Fill to the end of the string table
392 ZeroToOffset(OS, SymtabCmd->stroff + SymtabCmd->strsize);
393
394432 return Error::success();
395433 }
396434