@@ -307,8 +307,6 @@ static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
307
307
sym.verdefIndex = old.verdefIndex ;
308
308
sym.exportDynamic = true ;
309
309
sym.isUsedInRegularObj = true ;
310
- // A copy relocated alias may need a GOT entry.
311
- sym.needsGot = old.needsGot ;
312
310
}
313
311
314
312
// Reserve space in .bss or .bss.rel.ro for copy relocation.
@@ -353,7 +351,7 @@ static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
353
351
// to the variable in .bss. This kind of issue is sometimes very hard to
354
352
// debug. What's a solution? Instead of exporting a variable V from a DSO,
355
353
// define an accessor getV().
356
- template <class ELFT > static void addCopyRelSymbolImpl (SharedSymbol &ss) {
354
+ template <class ELFT > static void addCopyRelSymbol (SharedSymbol &ss) {
357
355
// Copy relocation against zero-sized symbol doesn't make sense.
358
356
uint64_t symSize = ss.getSize ();
359
357
if (symSize == 0 || ss.alignment == 0 )
@@ -384,26 +382,6 @@ template <class ELFT> static void addCopyRelSymbolImpl(SharedSymbol &ss) {
384
382
mainPart->relaDyn ->addSymbolReloc (target->copyRel , sec, 0 , ss);
385
383
}
386
384
387
- static void addCopyRelSymbol (SharedSymbol &ss) {
388
- const SharedFile &file = ss.getFile ();
389
- switch (file.ekind ) {
390
- case ELF32LEKind:
391
- addCopyRelSymbolImpl<ELF32LE>(ss);
392
- break ;
393
- case ELF32BEKind:
394
- addCopyRelSymbolImpl<ELF32BE>(ss);
395
- break ;
396
- case ELF64LEKind:
397
- addCopyRelSymbolImpl<ELF64LE>(ss);
398
- break ;
399
- case ELF64BEKind:
400
- addCopyRelSymbolImpl<ELF64BE>(ss);
401
- break ;
402
- default :
403
- llvm_unreachable (" " );
404
- }
405
- }
406
-
407
385
// MIPS has an odd notion of "paired" relocations to calculate addends.
408
386
// For example, if a relocation is of R_MIPS_HI16, there must be a
409
387
// R_MIPS_LO16 relocation after that, and an addend is calculated using
@@ -1067,7 +1045,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
1067
1045
" against symbol '" + toString (*ss) +
1068
1046
" '; recompile with -fPIC or remove '-z nocopyreloc'" +
1069
1047
getLocation (sec, sym, offset));
1070
- sym. needsCopy = true ;
1048
+ addCopyRelSymbol<ELFT>(*ss) ;
1071
1049
}
1072
1050
sec.relocations .push_back ({expr, type, offset, addend, &sym});
1073
1051
return ;
@@ -1105,8 +1083,20 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
1105
1083
errorOrWarn (" symbol '" + toString (sym) +
1106
1084
" ' cannot be preempted; recompile with -fPIE" +
1107
1085
getLocation (sec, sym, offset));
1108
- sym.needsCopy = true ;
1109
- sym.needsPlt = true ;
1086
+ if (!sym.isInPlt ())
1087
+ addPltEntry (in.plt , in.gotPlt , in.relaPlt , target->pltRel , sym);
1088
+ if (!sym.isDefined ()) {
1089
+ replaceWithDefined (
1090
+ sym, in.plt ,
1091
+ target->pltHeaderSize + target->pltEntrySize * sym.pltIndex , 0 );
1092
+ if (config->emachine == EM_PPC) {
1093
+ // PPC32 canonical PLT entries are at the beginning of .glink
1094
+ cast<Defined>(sym).value = in.plt ->headerSize ;
1095
+ in.plt ->headerSize += 16 ;
1096
+ cast<PPC32GlinkSection>(in.plt )->canonical_plts .push_back (&sym);
1097
+ }
1098
+ }
1099
+ sym.needsPltAddr = true ;
1110
1100
sec.relocations .push_back ({expr, type, offset, addend, &sym});
1111
1101
return ;
1112
1102
}
@@ -1435,23 +1425,116 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
1435
1425
return ;
1436
1426
}
1437
1427
1438
- if (needsGot (expr)) {
1439
- if (config->emachine == EM_MIPS) {
1440
- // MIPS ABI has special rules to process GOT entries and doesn't
1441
- // require relocation entries for them. A special case is TLS
1442
- // relocations. In that case dynamic loader applies dynamic
1443
- // relocations to initialize TLS GOT entries.
1444
- // See "Global Offset Table" in Chapter 5 in the following document
1445
- // for detailed description:
1446
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1447
- in.mipsGot ->addEntry (*sec.file , sym, addend, expr);
1448
- } else {
1449
- sym.needsGot = true ;
1428
+ // Non-preemptible ifuncs require special handling. First, handle the usual
1429
+ // case where the symbol isn't one of these.
1430
+ if (!sym.isGnuIFunc () || sym.isPreemptible ) {
1431
+ // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
1432
+ if (needsPlt (expr) && !sym.isInPlt ())
1433
+ addPltEntry (in.plt , in.gotPlt , in.relaPlt , target->pltRel , sym);
1434
+
1435
+ // Create a GOT slot if a relocation needs GOT.
1436
+ if (needsGot (expr)) {
1437
+ if (config->emachine == EM_MIPS) {
1438
+ // MIPS ABI has special rules to process GOT entries and doesn't
1439
+ // require relocation entries for them. A special case is TLS
1440
+ // relocations. In that case dynamic loader applies dynamic
1441
+ // relocations to initialize TLS GOT entries.
1442
+ // See "Global Offset Table" in Chapter 5 in the following document
1443
+ // for detailed description:
1444
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1445
+ in.mipsGot ->addEntry (*sec.file , sym, addend, expr);
1446
+ } else if (!sym.isInGot ()) {
1447
+ addGotEntry (sym);
1448
+ }
1450
1449
}
1451
- } else if (needsPlt (expr)) {
1452
- sym.needsPlt = true ;
1453
1450
} else {
1454
- sym.hasDirectReloc = true ;
1451
+ // Handle a reference to a non-preemptible ifunc. These are special in a
1452
+ // few ways:
1453
+ //
1454
+ // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
1455
+ // a fixed value. But assuming that all references to the ifunc are
1456
+ // GOT-generating or PLT-generating, the handling of an ifunc is
1457
+ // relatively straightforward. We create a PLT entry in Iplt, which is
1458
+ // usually at the end of .plt, which makes an indirect call using a
1459
+ // matching GOT entry in igotPlt, which is usually at the end of .got.plt.
1460
+ // The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
1461
+ // which is usually at the end of .rela.plt. Unlike most relocations in
1462
+ // .rela.plt, which may be evaluated lazily without -z now, dynamic
1463
+ // loaders evaluate IRELATIVE relocs eagerly, which means that for
1464
+ // IRELATIVE relocs only, GOT-generating relocations can point directly to
1465
+ // .got.plt without requiring a separate GOT entry.
1466
+ //
1467
+ // - Despite the fact that an ifunc does not have a fixed value, compilers
1468
+ // that are not passed -fPIC will assume that they do, and will emit
1469
+ // direct (non-GOT-generating, non-PLT-generating) relocations to the
1470
+ // symbol. This means that if a direct relocation to the symbol is
1471
+ // seen, the linker must set a value for the symbol, and this value must
1472
+ // be consistent no matter what type of reference is made to the symbol.
1473
+ // This can be done by creating a PLT entry for the symbol in the way
1474
+ // described above and making it canonical, that is, making all references
1475
+ // point to the PLT entry instead of the resolver. In lld we also store
1476
+ // the address of the PLT entry in the dynamic symbol table, which means
1477
+ // that the symbol will also have the same value in other modules.
1478
+ // Because the value loaded from the GOT needs to be consistent with
1479
+ // the value computed using a direct relocation, a non-preemptible ifunc
1480
+ // may end up with two GOT entries, one in .got.plt that points to the
1481
+ // address returned by the resolver and is used only by the PLT entry,
1482
+ // and another in .got that points to the PLT entry and is used by
1483
+ // GOT-generating relocations.
1484
+ //
1485
+ // - The fact that these symbols do not have a fixed value makes them an
1486
+ // exception to the general rule that a statically linked executable does
1487
+ // not require any form of dynamic relocation. To handle these relocations
1488
+ // correctly, the IRELATIVE relocations are stored in an array which a
1489
+ // statically linked executable's startup code must enumerate using the
1490
+ // linker-defined symbols __rela?_iplt_{start,end}.
1491
+ if (!sym.isInPlt ()) {
1492
+ // Create PLT and GOTPLT slots for the symbol.
1493
+ sym.isInIplt = true ;
1494
+
1495
+ // Create a copy of the symbol to use as the target of the IRELATIVE
1496
+ // relocation in the igotPlt. This is in case we make the PLT canonical
1497
+ // later, which would overwrite the original symbol.
1498
+ //
1499
+ // FIXME: Creating a copy of the symbol here is a bit of a hack. All
1500
+ // that's really needed to create the IRELATIVE is the section and value,
1501
+ // so ideally we should just need to copy those.
1502
+ auto *directSym = make<Defined>(cast<Defined>(sym));
1503
+ addPltEntry (in.iplt , in.igotPlt , in.relaIplt , target->iRelativeRel ,
1504
+ *directSym);
1505
+ sym.pltIndex = directSym->pltIndex ;
1506
+ }
1507
+ if (needsGot (expr)) {
1508
+ // Redirect GOT accesses to point to the Igot.
1509
+ //
1510
+ // This field is also used to keep track of whether we ever needed a GOT
1511
+ // entry. If we did and we make the PLT canonical later, we'll need to
1512
+ // create a GOT entry pointing to the PLT entry for Sym.
1513
+ sym.gotInIgot = true ;
1514
+ } else if (!needsPlt (expr)) {
1515
+ // Make the ifunc's PLT entry canonical by changing the value of its
1516
+ // symbol to redirect all references to point to it.
1517
+ auto &d = cast<Defined>(sym);
1518
+ d.section = in.iplt ;
1519
+ d.value = sym.pltIndex * target->ipltEntrySize ;
1520
+ d.size = 0 ;
1521
+ // It's important to set the symbol type here so that dynamic loaders
1522
+ // don't try to call the PLT as if it were an ifunc resolver.
1523
+ d.type = STT_FUNC;
1524
+
1525
+ if (sym.gotInIgot ) {
1526
+ // We previously encountered a GOT generating reference that we
1527
+ // redirected to the Igot. Now that the PLT entry is canonical we must
1528
+ // clear the redirection to the Igot and add a GOT entry. As we've
1529
+ // changed the symbol type to STT_FUNC future GOT generating references
1530
+ // will naturally use this GOT entry.
1531
+ //
1532
+ // We don't need to worry about creating a MIPS GOT here because ifuncs
1533
+ // aren't a thing on MIPS.
1534
+ sym.gotInIgot = false ;
1535
+ addGotEntry (sym);
1536
+ }
1537
+ }
1455
1538
}
1456
1539
1457
1540
processRelocAux<ELFT>(sec, expr, type, offset, sym, addend);
@@ -1532,121 +1615,6 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &s) {
1532
1615
scanRelocs<ELFT>(s, rels.relas );
1533
1616
}
1534
1617
1535
- static bool handleNonPreemptibleIfunc (Symbol &sym) {
1536
- // Handle a reference to a non-preemptible ifunc. These are special in a
1537
- // few ways:
1538
- //
1539
- // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
1540
- // a fixed value. But assuming that all references to the ifunc are
1541
- // GOT-generating or PLT-generating, the handling of an ifunc is
1542
- // relatively straightforward. We create a PLT entry in Iplt, which is
1543
- // usually at the end of .plt, which makes an indirect call using a
1544
- // matching GOT entry in igotPlt, which is usually at the end of .got.plt.
1545
- // The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
1546
- // which is usually at the end of .rela.plt. Unlike most relocations in
1547
- // .rela.plt, which may be evaluated lazily without -z now, dynamic
1548
- // loaders evaluate IRELATIVE relocs eagerly, which means that for
1549
- // IRELATIVE relocs only, GOT-generating relocations can point directly to
1550
- // .got.plt without requiring a separate GOT entry.
1551
- //
1552
- // - Despite the fact that an ifunc does not have a fixed value, compilers
1553
- // that are not passed -fPIC will assume that they do, and will emit
1554
- // direct (non-GOT-generating, non-PLT-generating) relocations to the
1555
- // symbol. This means that if a direct relocation to the symbol is
1556
- // seen, the linker must set a value for the symbol, and this value must
1557
- // be consistent no matter what type of reference is made to the symbol.
1558
- // This can be done by creating a PLT entry for the symbol in the way
1559
- // described above and making it canonical, that is, making all references
1560
- // point to the PLT entry instead of the resolver. In lld we also store
1561
- // the address of the PLT entry in the dynamic symbol table, which means
1562
- // that the symbol will also have the same value in other modules.
1563
- // Because the value loaded from the GOT needs to be consistent with
1564
- // the value computed using a direct relocation, a non-preemptible ifunc
1565
- // may end up with two GOT entries, one in .got.plt that points to the
1566
- // address returned by the resolver and is used only by the PLT entry,
1567
- // and another in .got that points to the PLT entry and is used by
1568
- // GOT-generating relocations.
1569
- //
1570
- // - The fact that these symbols do not have a fixed value makes them an
1571
- // exception to the general rule that a statically linked executable does
1572
- // not require any form of dynamic relocation. To handle these relocations
1573
- // correctly, the IRELATIVE relocations are stored in an array which a
1574
- // statically linked executable's startup code must enumerate using the
1575
- // linker-defined symbols __rela?_iplt_{start,end}.
1576
- if (!sym.isGnuIFunc () || sym.isPreemptible || config->zIfuncNoplt )
1577
- return false ;
1578
-
1579
- sym.isInIplt = true ;
1580
-
1581
- // Create an Iplt and the associated IRELATIVE relocation pointing to the
1582
- // original section/value pairs. For non-GOT non-PLT relocation case below, we
1583
- // may alter section/value, so create a copy of the symbol to make
1584
- // section/value fixed.
1585
- auto *directSym = make<Defined>(cast<Defined>(sym));
1586
- addPltEntry (in.iplt , in.igotPlt , in.relaIplt , target->iRelativeRel ,
1587
- *directSym);
1588
- sym.pltIndex = directSym->pltIndex ;
1589
-
1590
- if (sym.hasDirectReloc ) {
1591
- // Change the value to the IPLT and redirect all references to it.
1592
- auto &d = cast<Defined>(sym);
1593
- d.section = in.iplt ;
1594
- d.value = sym.pltIndex * target->ipltEntrySize ;
1595
- d.size = 0 ;
1596
- // It's important to set the symbol type here so that dynamic loaders
1597
- // don't try to call the PLT as if it were an ifunc resolver.
1598
- d.type = STT_FUNC;
1599
-
1600
- if (sym.needsGot )
1601
- addGotEntry (sym);
1602
- } else if (sym.needsGot ) {
1603
- // Redirect GOT accesses to point to the Igot.
1604
- sym.gotInIgot = true ;
1605
- }
1606
- return true ;
1607
- }
1608
-
1609
- void elf::postScanRelocations () {
1610
- auto fn = [](Symbol &sym) {
1611
- if (handleNonPreemptibleIfunc (sym))
1612
- return ;
1613
- if (sym.needsGot )
1614
- addGotEntry (sym);
1615
- if (sym.needsPlt )
1616
- addPltEntry (in.plt , in.gotPlt , in.relaPlt , target->pltRel , sym);
1617
- if (sym.needsCopy ) {
1618
- if (sym.isObject ()) {
1619
- addCopyRelSymbol (cast<SharedSymbol>(sym));
1620
- // needsCopy is cleared for sym and its aliases so that in later
1621
- // iterations aliases won't cause redundant copies.
1622
- assert (!sym.needsCopy );
1623
- } else {
1624
- assert (sym.isFunc () && sym.needsPlt );
1625
- if (!sym.isDefined ()) {
1626
- replaceWithDefined (
1627
- sym, in.plt ,
1628
- target->pltHeaderSize + target->pltEntrySize * sym.pltIndex , 0 );
1629
- sym.needsCopy = true ;
1630
- if (config->emachine == EM_PPC) {
1631
- // PPC32 canonical PLT entries are at the beginning of .glink
1632
- cast<Defined>(sym).value = in.plt ->headerSize ;
1633
- in.plt ->headerSize += 16 ;
1634
- cast<PPC32GlinkSection>(in.plt )->canonical_plts .push_back (&sym);
1635
- }
1636
- }
1637
- }
1638
- }
1639
- };
1640
- for (Symbol *sym : symtab->symbols ())
1641
- fn (*sym);
1642
-
1643
- // Local symbols may need the aforementioned non-preemptible ifunc and GOT
1644
- // handling. They don't need regular PLT.
1645
- for (InputFile *file : objectFiles)
1646
- for (Symbol *sym : cast<ELFFileBase>(file)->getLocalSymbols ())
1647
- fn (*sym);
1648
- }
1649
-
1650
1618
static bool mergeCmp (const InputSection *a, const InputSection *b) {
1651
1619
// std::merge requires a strict weak ordering.
1652
1620
if (a->outSecOff < b->outSecOff )
0 commit comments