@@ -277,6 +277,12 @@ struct Binding {
277
277
uint64_t offset = 0 ;
278
278
int64_t addend = 0 ;
279
279
};
280
+ struct BindIR {
281
+ // Default value of 0xF0 is not valid opcode and should make the program
282
+ // scream instead of accidentally writing "valid" values.
283
+ uint8_t opcode = 0xF0 ;
284
+ uint64_t data = 0 ;
285
+ };
280
286
} // namespace
281
287
282
288
// Encode a sequence of opcodes that tell dyld to write the address of symbol +
@@ -287,32 +293,65 @@ struct Binding {
287
293
// lastBinding.
288
294
static void encodeBinding (const OutputSection *osec, uint64_t outSecOff,
289
295
int64_t addend, Binding &lastBinding,
290
- raw_svector_ostream &os ) {
296
+ std::vector<BindIR> &opcodes ) {
291
297
OutputSegment *seg = osec->parent ;
292
298
uint64_t offset = osec->getSegmentOffset () + outSecOff;
293
299
if (lastBinding.segment != seg) {
294
- os << static_cast <uint8_t >(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
295
- seg->index );
296
- encodeULEB128 (offset, os);
300
+ BindIR op = {
301
+ static_cast <uint8_t >(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB |
302
+ seg->index ), // opcode
303
+ offset // data
304
+ };
305
+ opcodes.push_back (op);
297
306
lastBinding.segment = seg;
298
307
lastBinding.offset = offset;
299
308
} else if (lastBinding.offset != offset) {
300
- os << static_cast <uint8_t >(BIND_OPCODE_ADD_ADDR_ULEB);
301
- encodeULEB128 (offset - lastBinding.offset , os);
309
+ BindIR op = {
310
+ static_cast <uint8_t >(BIND_OPCODE_ADD_ADDR_ULEB), // opcode
311
+ offset - lastBinding.offset // data
312
+ };
313
+ opcodes.push_back (op);
302
314
lastBinding.offset = offset;
303
315
}
304
316
305
317
if (lastBinding.addend != addend) {
306
- os << static_cast <uint8_t >(BIND_OPCODE_SET_ADDEND_SLEB);
307
- encodeSLEB128 (addend, os);
318
+ BindIR op = {
319
+ static_cast <uint8_t >(BIND_OPCODE_SET_ADDEND_SLEB), // opcode
320
+ static_cast <uint64_t >(addend) // data
321
+ };
322
+ opcodes.push_back (op);
308
323
lastBinding.addend = addend;
309
324
}
310
325
311
- os << static_cast <uint8_t >(BIND_OPCODE_DO_BIND);
326
+ BindIR op = {
327
+ static_cast <uint8_t >(BIND_OPCODE_DO_BIND), // opcode
328
+ 0 // data
329
+ };
330
+ opcodes.push_back (op);
312
331
// DO_BIND causes dyld to both perform the binding and increment the offset
313
332
lastBinding.offset += target->wordSize ;
314
333
}
315
334
335
+ static void flushOpcodes (const BindIR &op, raw_svector_ostream &os) {
336
+ uint8_t opcode = op.opcode & BIND_OPCODE_MASK;
337
+ switch (opcode) {
338
+ case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
339
+ case BIND_OPCODE_ADD_ADDR_ULEB:
340
+ os << op.opcode ;
341
+ encodeULEB128 (op.data , os);
342
+ break ;
343
+ case BIND_OPCODE_SET_ADDEND_SLEB:
344
+ os << op.opcode ;
345
+ encodeSLEB128 (static_cast <int64_t >(op.data ), os);
346
+ break ;
347
+ case BIND_OPCODE_DO_BIND:
348
+ os << op.opcode ;
349
+ break ;
350
+ default :
351
+ llvm_unreachable (" cannot bind to an unrecognized symbol" );
352
+ }
353
+ }
354
+
316
355
// Non-weak bindings need to have their dylib ordinal encoded as well.
317
356
static int16_t ordinalForDylibSymbol (const DylibSymbol &dysym) {
318
357
if (config->namespaceKind == NamespaceKind::flat || dysym.isDynamicLookup ())
@@ -392,9 +431,6 @@ void BindingSection::finalizeContents() {
392
431
for (auto &p : sortBindings (bindingsMap)) {
393
432
const DylibSymbol *sym = p.first ;
394
433
std::vector<BindingEntry> &bindings = p.second ;
395
- llvm::sort (bindings, [](const BindingEntry &a, const BindingEntry &b) {
396
- return a.target .getVA () < b.target .getVA ();
397
- });
398
434
uint8_t flags = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM;
399
435
if (sym->isWeakRef ())
400
436
flags |= BIND_SYMBOL_FLAGS_WEAK_IMPORT;
@@ -405,10 +441,13 @@ void BindingSection::finalizeContents() {
405
441
encodeDylibOrdinal (ordinal, os);
406
442
lastOrdinal = ordinal;
407
443
}
444
+ std::vector<BindIR> opcodes;
408
445
for (const BindingEntry &b : bindings)
409
446
encodeBinding (b.target .isec ->parent ,
410
447
b.target .isec ->getOffset (b.target .offset ), b.addend ,
411
- lastBinding, os);
448
+ lastBinding, opcodes);
449
+ for (const auto &op : opcodes)
450
+ flushOpcodes (op, os);
412
451
}
413
452
if (!bindingsMap.empty ())
414
453
os << static_cast <uint8_t >(BIND_OPCODE_DONE);
@@ -434,10 +473,13 @@ void WeakBindingSection::finalizeContents() {
434
473
os << static_cast <uint8_t >(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
435
474
<< sym->getName () << ' \0 '
436
475
<< static_cast <uint8_t >(BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER);
476
+ std::vector<BindIR> opcodes;
437
477
for (const BindingEntry &b : bindings)
438
478
encodeBinding (b.target .isec ->parent ,
439
479
b.target .isec ->getOffset (b.target .offset ), b.addend ,
440
- lastBinding, os);
480
+ lastBinding, opcodes);
481
+ for (const auto &op : opcodes)
482
+ flushOpcodes (op, os);
441
483
}
442
484
if (!bindingsMap.empty () || !definitions.empty ())
443
485
os << static_cast <uint8_t >(BIND_OPCODE_DONE);
0 commit comments