39
39
#include " llvm/MC/StringTableBuilder.h"
40
40
#include " llvm/Support/Alignment.h"
41
41
#include " llvm/Support/Casting.h"
42
+ #include " llvm/Support/CommandLine.h"
42
43
#include " llvm/Support/Compression.h"
43
44
#include " llvm/Support/Endian.h"
44
45
#include " llvm/Support/EndianStream.h"
@@ -256,7 +257,7 @@ class ELFObjectWriter : public MCObjectWriter {
256
257
void recordRelocation (MCAssembler &Asm, const MCFragment *Fragment,
257
258
const MCFixup &Fixup, MCValue Target,
258
259
uint64_t &FixedValue) override ;
259
- bool usesRela (const MCSectionELF &Sec) const ;
260
+ bool usesRela (const MCTargetOptions *TO, const MCSectionELF &Sec) const ;
260
261
261
262
void executePostLayoutBinding (MCAssembler &Asm,
262
263
const MCAsmLayout &Layout) override ;
@@ -810,7 +811,15 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
810
811
Flags = ELF::SHF_GROUP;
811
812
812
813
const StringRef SectionName = Sec.getName ();
813
- const bool Rela = OWriter.usesRela (Sec);
814
+ const MCTargetOptions *TO = Ctx.getTargetOptions ();
815
+ if (TO && TO->Crel ) {
816
+ MCSectionELF *RelaSection =
817
+ Ctx.createELFRelSection (" .crel" + SectionName, ELF::SHT_CREL, Flags,
818
+ /* EntrySize=*/ 1 , Sec.getGroup (), &Sec);
819
+ return RelaSection;
820
+ }
821
+
822
+ const bool Rela = OWriter.usesRela (TO, Sec);
814
823
unsigned EntrySize;
815
824
if (Rela)
816
825
EntrySize = is64Bit () ? sizeof (ELF::Elf64_Rela) : sizeof (ELF::Elf32_Rela);
@@ -912,20 +921,61 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
912
921
WriteWord (EntrySize); // sh_entsize
913
922
}
914
923
924
+ template <class uint >
925
+ static void encodeCrel (ArrayRef<ELFRelocationEntry> Relocs, raw_ostream &OS) {
926
+ uint OffsetMask = 8 , Offset = 0 , Addend = 0 ;
927
+ uint32_t SymIdx = 0 , Type = 0 ;
928
+ // hdr & 4 indicates 3 flag bits in delta offset and flags members.
929
+ for (const ELFRelocationEntry &Entry : Relocs)
930
+ OffsetMask |= Entry.Offset ;
931
+ const int Shift = llvm::countr_zero (OffsetMask);
932
+ encodeULEB128 (Relocs.size () * 8 + ELF::CREL_HDR_ADDEND + Shift, OS);
933
+ for (const ELFRelocationEntry &Entry : Relocs) {
934
+ // The delta offset and flags member may be larger than uint64_t. Special
935
+ // case the first byte (3 flag bits and 4 offset bits). Other ULEB128 bytes
936
+ // encode the remaining delta offset bits.
937
+ auto DeltaOffset = static_cast <uint>((Entry.Offset - Offset) >> Shift);
938
+ Offset = Entry.Offset ;
939
+ uint32_t CurSymIdx = Entry.Symbol ? Entry.Symbol ->getIndex () : 0 ;
940
+ uint8_t B = (DeltaOffset << 3 ) + (SymIdx != CurSymIdx) +
941
+ (Type != Entry.Type ? 2 : 0 ) + (Addend != Entry.Addend ? 4 : 0 );
942
+ if (DeltaOffset < 0x10 ) {
943
+ OS << char (B);
944
+ } else {
945
+ OS << char (B | 0x80 );
946
+ encodeULEB128 (DeltaOffset >> 4 , OS);
947
+ }
948
+ // Delta symidx/type/addend members (SLEB128).
949
+ if (B & 1 ) {
950
+ encodeSLEB128 (static_cast <int32_t >(CurSymIdx - SymIdx), OS);
951
+ SymIdx = CurSymIdx;
952
+ }
953
+ if (B & 2 ) {
954
+ encodeSLEB128 (static_cast <int32_t >(Entry.Type - Type), OS);
955
+ Type = Entry.Type ;
956
+ }
957
+ if (B & 4 ) {
958
+ encodeSLEB128 (std::make_signed_t <uint>(Entry.Addend - Addend), OS);
959
+ Addend = Entry.Addend ;
960
+ }
961
+ }
962
+ }
963
+
915
964
void ELFWriter::writeRelocations (const MCAssembler &Asm,
916
965
const MCSectionELF &Sec) {
917
966
std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations [&Sec];
918
- const bool Rela = OWriter.usesRela (Sec);
967
+ const MCTargetOptions *TO = Asm.getContext ().getTargetOptions ();
968
+ const bool Rela = OWriter.usesRela (TO, Sec);
919
969
920
970
// Sort the relocation entries. MIPS needs this.
921
971
OWriter.TargetObjectWriter ->sortRelocs (Asm, Relocs);
922
972
923
973
if (OWriter.TargetObjectWriter ->getEMachine () == ELF::EM_MIPS) {
924
974
for (const ELFRelocationEntry &Entry : Relocs) {
925
- uint32_t Symidx = Entry.Symbol ? Entry.Symbol ->getIndex () : 0 ;
975
+ uint32_t SymIdx = Entry.Symbol ? Entry.Symbol ->getIndex () : 0 ;
926
976
if (is64Bit ()) {
927
977
write (Entry.Offset );
928
- write (uint32_t (Symidx ));
978
+ write (uint32_t (SymIdx ));
929
979
write (OWriter.TargetObjectWriter ->getRSsym (Entry.Type ));
930
980
write (OWriter.TargetObjectWriter ->getRType3 (Entry.Type ));
931
981
write (OWriter.TargetObjectWriter ->getRType2 (Entry.Type ));
@@ -935,7 +985,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm,
935
985
} else {
936
986
write (uint32_t (Entry.Offset ));
937
987
ELF::Elf32_Rela ERE32;
938
- ERE32.setSymbolAndType (Symidx , Entry.Type );
988
+ ERE32.setSymbolAndType (SymIdx , Entry.Type );
939
989
write (ERE32.r_info );
940
990
if (Rela)
941
991
write (uint32_t (Entry.Addend ));
@@ -955,24 +1005,29 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm,
955
1005
}
956
1006
}
957
1007
}
958
- return ;
959
- }
960
- for (const ELFRelocationEntry &Entry : Relocs) {
961
- uint32_t Symidx = Entry.Symbol ? Entry.Symbol ->getIndex () : 0 ;
962
- if (is64Bit ()) {
963
- write (Entry.Offset );
964
- ELF::Elf64_Rela ERE;
965
- ERE.setSymbolAndType (Symidx, Entry.Type );
966
- write (ERE.r_info );
967
- if (Rela)
968
- write (Entry.Addend );
969
- } else {
970
- write (uint32_t (Entry.Offset ));
971
- ELF::Elf32_Rela ERE;
972
- ERE.setSymbolAndType (Symidx, Entry.Type );
973
- write (ERE.r_info );
974
- if (Rela)
975
- write (uint32_t (Entry.Addend ));
1008
+ } else if (TO && TO->Crel ) {
1009
+ if (is64Bit ())
1010
+ encodeCrel<uint64_t >(Relocs, W.OS );
1011
+ else
1012
+ encodeCrel<uint32_t >(Relocs, W.OS );
1013
+ } else {
1014
+ for (const ELFRelocationEntry &Entry : Relocs) {
1015
+ uint32_t Symidx = Entry.Symbol ? Entry.Symbol ->getIndex () : 0 ;
1016
+ if (is64Bit ()) {
1017
+ write (Entry.Offset );
1018
+ ELF::Elf64_Rela ERE;
1019
+ ERE.setSymbolAndType (Symidx, Entry.Type );
1020
+ write (ERE.r_info );
1021
+ if (Rela)
1022
+ write (Entry.Addend );
1023
+ } else {
1024
+ write (uint32_t (Entry.Offset ));
1025
+ ELF::Elf32_Rela ERE;
1026
+ ERE.setSymbolAndType (Symidx, Entry.Type );
1027
+ write (ERE.r_info );
1028
+ if (Rela)
1029
+ write (uint32_t (Entry.Addend ));
1030
+ }
976
1031
}
977
1032
}
978
1033
}
@@ -992,7 +1047,8 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
992
1047
llvm_unreachable (" SHT_DYNAMIC in a relocatable object" );
993
1048
994
1049
case ELF::SHT_REL:
995
- case ELF::SHT_RELA: {
1050
+ case ELF::SHT_RELA:
1051
+ case ELF::SHT_CREL: {
996
1052
sh_link = SymbolTableIndex;
997
1053
assert (sh_link && " .symtab not found" );
998
1054
const MCSection *InfoSection = Section.getLinkedToSection ();
@@ -1417,6 +1473,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
1417
1473
uint64_t C = Target.getConstant ();
1418
1474
uint64_t FixupOffset = Asm.getFragmentOffset (*Fragment) + Fixup.getOffset ();
1419
1475
MCContext &Ctx = Asm.getContext ();
1476
+ const MCTargetOptions *TO = Ctx.getTargetOptions ();
1420
1477
1421
1478
if (const MCSymbolRefExpr *RefB = Target.getSymB ()) {
1422
1479
const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol ());
@@ -1472,7 +1529,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
1472
1529
FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined ()
1473
1530
? C + Asm.getSymbolOffset (*SymA)
1474
1531
: C;
1475
- if (usesRela (FixupSection)) {
1532
+ if (usesRela (TO, FixupSection)) {
1476
1533
Addend = FixedValue;
1477
1534
FixedValue = 0 ;
1478
1535
}
@@ -1501,9 +1558,11 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
1501
1558
Relocations[&FixupSection].push_back (Rec);
1502
1559
}
1503
1560
1504
- bool ELFObjectWriter::usesRela (const MCSectionELF &Sec) const {
1505
- return hasRelocationAddend () &&
1506
- Sec.getType () != ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
1561
+ bool ELFObjectWriter::usesRela (const MCTargetOptions *TO,
1562
+ const MCSectionELF &Sec) const {
1563
+ return (hasRelocationAddend () &&
1564
+ Sec.getType () != ELF::SHT_LLVM_CALL_GRAPH_PROFILE) ||
1565
+ (TO && TO->Crel );
1507
1566
}
1508
1567
1509
1568
bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl (
0 commit comments