Index: lld/trunk/ELF/AArch64ErrataFix.h =================================================================== --- lld/trunk/ELF/AArch64ErrataFix.h +++ lld/trunk/ELF/AArch64ErrataFix.h @@ -29,19 +29,19 @@ private: std::vector - patchInputSectionDescription(InputSectionDescription &ISD); + patchInputSectionDescription(InputSectionDescription &isd); - void insertPatches(InputSectionDescription &ISD, - std::vector &Patches); + void insertPatches(InputSectionDescription &isd, + std::vector &patches); void init(); // A cache of the mapping symbols defined by the InputSecion sorted in order // of ascending value with redundant symbols removed. These describe // the ranges of code and data in an executable InputSection. - std::map> SectionMap; + std::map> sectionMap; - bool Initialized = false; + bool initialized = false; }; } // namespace elf Index: lld/trunk/ELF/AArch64ErrataFix.cpp =================================================================== --- lld/trunk/ELF/AArch64ErrataFix.cpp +++ lld/trunk/ELF/AArch64ErrataFix.cpp @@ -56,8 +56,8 @@ // ADRP // | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) | -static bool isADRP(uint32_t Instr) { - return (Instr & 0x9f000000) == 0x90000000; +static bool isADRP(uint32_t instr) { + return (instr & 0x9f000000) == 0x90000000; } // Load and store bit patterns from ARMv8-A ARM ARM. @@ -66,8 +66,8 @@ // All loads and stores have 1 (at bit postion 27), (0 at bit position 25). // | op0 x op1 (2) | 1 op2 0 op3 (2) | x | op4 (5) | xxxx | op5 (2) | x (10) | -static bool isLoadStoreClass(uint32_t Instr) { - return (Instr & 0x0a000000) == 0x08000000; +static bool isLoadStoreClass(uint32_t instr) { + return (instr & 0x0a000000) == 0x08000000; } // LDN/STN multiple no offset @@ -82,20 +82,20 @@ // opcode == 0110 ST1 3 registers. // opcode == 0111 ST1 1 register. // opcode == 1010 ST1 2 registers. -static bool isST1MultipleOpcode(uint32_t Instr) { - return (Instr & 0x0000f000) == 0x00002000 || - (Instr & 0x0000f000) == 0x00006000 || - (Instr & 0x0000f000) == 0x00007000 || - (Instr & 0x0000f000) == 0x0000a000; +static bool isST1MultipleOpcode(uint32_t instr) { + return (instr & 0x0000f000) == 0x00002000 || + (instr & 0x0000f000) == 0x00006000 || + (instr & 0x0000f000) == 0x00007000 || + (instr & 0x0000f000) == 0x0000a000; } -static bool isST1Multiple(uint32_t Instr) { - return (Instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(Instr); +static bool isST1Multiple(uint32_t instr) { + return (instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(instr); } // Writes to Rn (writeback). -static bool isST1MultiplePost(uint32_t Instr) { - return (Instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(Instr); +static bool isST1MultiplePost(uint32_t instr) { + return (instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(instr); } // LDN/STN single no offset @@ -110,41 +110,41 @@ // opcode == 000 ST1 8-bit. // opcode == 010 ST1 16-bit. // opcode == 100 ST1 32 or 64-bit (Size determines which). -static bool isST1SingleOpcode(uint32_t Instr) { - return (Instr & 0x0040e000) == 0x00000000 || - (Instr & 0x0040e000) == 0x00004000 || - (Instr & 0x0040e000) == 0x00008000; +static bool isST1SingleOpcode(uint32_t instr) { + return (instr & 0x0040e000) == 0x00000000 || + (instr & 0x0040e000) == 0x00004000 || + (instr & 0x0040e000) == 0x00008000; } -static bool isST1Single(uint32_t Instr) { - return (Instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(Instr); +static bool isST1Single(uint32_t instr) { + return (instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(instr); } // Writes to Rn (writeback). -static bool isST1SinglePost(uint32_t Instr) { - return (Instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(Instr); +static bool isST1SinglePost(uint32_t instr) { + return (instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(instr); } -static bool isST1(uint32_t Instr) { - return isST1Multiple(Instr) || isST1MultiplePost(Instr) || - isST1Single(Instr) || isST1SinglePost(Instr); +static bool isST1(uint32_t instr) { + return isST1Multiple(instr) || isST1MultiplePost(instr) || + isST1Single(instr) || isST1SinglePost(instr); } // Load/store exclusive // | size (2) 00 | 1000 | o2 L o1 | Rs (5) | o0 | Rt2 (5) | Rn (5) | Rt (5) | // L == 0 for Stores. -static bool isLoadStoreExclusive(uint32_t Instr) { - return (Instr & 0x3f000000) == 0x08000000; +static bool isLoadStoreExclusive(uint32_t instr) { + return (instr & 0x3f000000) == 0x08000000; } -static bool isLoadExclusive(uint32_t Instr) { - return (Instr & 0x3f400000) == 0x08400000; +static bool isLoadExclusive(uint32_t instr) { + return (instr & 0x3f400000) == 0x08400000; } // Load register literal // | opc (2) 01 | 1 V 00 | imm19 | Rt (5) | -static bool isLoadLiteral(uint32_t Instr) { - return (Instr & 0x3b000000) == 0x18000000; +static bool isLoadLiteral(uint32_t instr) { + return (instr & 0x3b000000) == 0x18000000; } // Load/store no-allocate pair @@ -152,8 +152,8 @@ // | opc (2) 10 | 1 V 00 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | // L == 0 for stores. // Never writes to register -static bool isSTNP(uint32_t Instr) { - return (Instr & 0x3bc00000) == 0x28000000; +static bool isSTNP(uint32_t instr) { + return (instr & 0x3bc00000) == 0x28000000; } // Load/store register pair @@ -161,69 +161,69 @@ // | opc (2) 10 | 1 V 00 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | // L == 0 for stores, V == 0 for Scalar, V == 1 for Simd/FP // Writes to Rn. -static bool isSTPPost(uint32_t Instr) { - return (Instr & 0x3bc00000) == 0x28800000; +static bool isSTPPost(uint32_t instr) { + return (instr & 0x3bc00000) == 0x28800000; } // (offset) // | opc (2) 10 | 1 V 01 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | -static bool isSTPOffset(uint32_t Instr) { - return (Instr & 0x3bc00000) == 0x29000000; +static bool isSTPOffset(uint32_t instr) { + return (instr & 0x3bc00000) == 0x29000000; } // (pre-index) // | opc (2) 10 | 1 V 01 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) | // Writes to Rn. -static bool isSTPPre(uint32_t Instr) { - return (Instr & 0x3bc00000) == 0x29800000; +static bool isSTPPre(uint32_t instr) { + return (instr & 0x3bc00000) == 0x29800000; } -static bool isSTP(uint32_t Instr) { - return isSTPPost(Instr) || isSTPOffset(Instr) || isSTPPre(Instr); +static bool isSTP(uint32_t instr) { + return isSTPPost(instr) || isSTPOffset(instr) || isSTPPre(instr); } // Load/store register (unscaled immediate) // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 00 | Rn (5) | Rt (5) | // V == 0 for Scalar, V == 1 for Simd/FP. -static bool isLoadStoreUnscaled(uint32_t Instr) { - return (Instr & 0x3b000c00) == 0x38000000; +static bool isLoadStoreUnscaled(uint32_t instr) { + return (instr & 0x3b000c00) == 0x38000000; } // Load/store register (immediate post-indexed) // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 01 | Rn (5) | Rt (5) | -static bool isLoadStoreImmediatePost(uint32_t Instr) { - return (Instr & 0x3b200c00) == 0x38000400; +static bool isLoadStoreImmediatePost(uint32_t instr) { + return (instr & 0x3b200c00) == 0x38000400; } // Load/store register (unprivileged) // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 10 | Rn (5) | Rt (5) | -static bool isLoadStoreUnpriv(uint32_t Instr) { - return (Instr & 0x3b200c00) == 0x38000800; +static bool isLoadStoreUnpriv(uint32_t instr) { + return (instr & 0x3b200c00) == 0x38000800; } // Load/store register (immediate pre-indexed) // | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 11 | Rn (5) | Rt (5) | -static bool isLoadStoreImmediatePre(uint32_t Instr) { - return (Instr & 0x3b200c00) == 0x38000c00; +static bool isLoadStoreImmediatePre(uint32_t instr) { + return (instr & 0x3b200c00) == 0x38000c00; } // Load/store register (register offset) // | size (2) 11 | 1 V 00 | opc (2) 1 | Rm (5) | option (3) S | 10 | Rn | Rt | -static bool isLoadStoreRegisterOff(uint32_t Instr) { - return (Instr & 0x3b200c00) == 0x38200800; +static bool isLoadStoreRegisterOff(uint32_t instr) { + return (instr & 0x3b200c00) == 0x38200800; } // Load/store register (unsigned immediate) // | size (2) 11 | 1 V 01 | opc (2) | imm12 | Rn (5) | Rt (5) | -static bool isLoadStoreRegisterUnsigned(uint32_t Instr) { - return (Instr & 0x3b000000) == 0x39000000; +static bool isLoadStoreRegisterUnsigned(uint32_t instr) { + return (instr & 0x3b000000) == 0x39000000; } // Rt is always in bit position 0 - 4. -static uint32_t getRt(uint32_t Instr) { return (Instr & 0x1f); } +static uint32_t getRt(uint32_t instr) { return (instr & 0x1f); } // Rn is always in bit position 5 - 9. -static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; } +static uint32_t getRn(uint32_t instr) { return (instr >> 5) & 0x1f; } // C4.1.2 Branches, Exception Generating and System instructions // | op0 (3) 1 | 01 op1 (4) | x (22) | @@ -232,41 +232,41 @@ // op0 == x00 101 op1 == xxxx Unconditional Branch immediate. // op0 == x01 101 op1 == 0xxx Compare and branch immediate. // op0 == x01 101 op1 == 1xxx Test and branch immediate. -static bool isBranch(uint32_t Instr) { - return ((Instr & 0xfe000000) == 0xd6000000) || // Cond branch. - ((Instr & 0xfe000000) == 0x54000000) || // Uncond branch reg. - ((Instr & 0x7c000000) == 0x14000000) || // Uncond branch imm. - ((Instr & 0x7c000000) == 0x34000000); // Compare and test branch. +static bool isBranch(uint32_t instr) { + return ((instr & 0xfe000000) == 0xd6000000) || // Cond branch. + ((instr & 0xfe000000) == 0x54000000) || // Uncond branch reg. + ((instr & 0x7c000000) == 0x14000000) || // Uncond branch imm. + ((instr & 0x7c000000) == 0x34000000); // Compare and test branch. } -static bool isV8SingleRegisterNonStructureLoadStore(uint32_t Instr) { - return isLoadStoreUnscaled(Instr) || isLoadStoreImmediatePost(Instr) || - isLoadStoreUnpriv(Instr) || isLoadStoreImmediatePre(Instr) || - isLoadStoreRegisterOff(Instr) || isLoadStoreRegisterUnsigned(Instr); +static bool isV8SingleRegisterNonStructureLoadStore(uint32_t instr) { + return isLoadStoreUnscaled(instr) || isLoadStoreImmediatePost(instr) || + isLoadStoreUnpriv(instr) || isLoadStoreImmediatePre(instr) || + isLoadStoreRegisterOff(instr) || isLoadStoreRegisterUnsigned(instr); } // Note that this function refers to v8.0 only and does not include the // additional load and store instructions added for in later revisions of // the architecture such as the Atomic memory operations introduced // in v8.1. -static bool isV8NonStructureLoad(uint32_t Instr) { - if (isLoadExclusive(Instr)) +static bool isV8NonStructureLoad(uint32_t instr) { + if (isLoadExclusive(instr)) return true; - if (isLoadLiteral(Instr)) + if (isLoadLiteral(instr)) return true; - else if (isV8SingleRegisterNonStructureLoadStore(Instr)) { + else if (isV8SingleRegisterNonStructureLoadStore(instr)) { // For Load and Store single register, Loads are derived from a // combination of the Size, V and Opc fields. - uint32_t Size = (Instr >> 30) & 0xff; - uint32_t V = (Instr >> 26) & 0x1; - uint32_t Opc = (Instr >> 22) & 0x3; + uint32_t size = (instr >> 30) & 0xff; + uint32_t v = (instr >> 26) & 0x1; + uint32_t opc = (instr >> 22) & 0x3; // For the load and store instructions that we are decoding. // Opc == 0 are all stores. // Opc == 1 with a couple of exceptions are loads. The exceptions are: // Size == 00 (0), V == 1, Opc == 10 (2) which is a store and // Size == 11 (3), V == 0, Opc == 10 (2) which is a prefetch. - return Opc != 0 && !(Size == 0 && V == 1 && Opc == 2) && - !(Size == 3 && V == 0 && Opc == 2); + return opc != 0 && !(size == 0 && v == 1 && opc == 2) && + !(size == 3 && v == 0 && opc == 2); } return false; } @@ -275,18 +275,18 @@ // needed for errata 843419. // Instruction with writeback updates the index register after the load/store. -static bool hasWriteback(uint32_t Instr) { - return isLoadStoreImmediatePre(Instr) || isLoadStoreImmediatePost(Instr) || - isSTPPre(Instr) || isSTPPost(Instr) || isST1SinglePost(Instr) || - isST1MultiplePost(Instr); +static bool hasWriteback(uint32_t instr) { + return isLoadStoreImmediatePre(instr) || isLoadStoreImmediatePost(instr) || + isSTPPre(instr) || isSTPPost(instr) || isST1SinglePost(instr) || + isST1MultiplePost(instr); } // For the load and store class of instructions, a load can write to the // destination register, a load and a store can write to the base register when // the instruction has writeback. -static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) { - return (isV8NonStructureLoad(Instr) && getRt(Instr) == Reg) || - (hasWriteback(Instr) && getRn(Instr) == Reg); +static bool doesLoadStoreWriteToReg(uint32_t instr, uint32_t reg) { + return (isV8NonStructureLoad(instr) && getRt(instr) == reg) || + (hasWriteback(instr) && getRn(instr) == reg); } // Scanner for Cortex-A53 errata 843419 @@ -318,18 +318,18 @@ // Return true if the Instruction sequence Adrp, Instr2, and Instr4 match // the erratum sequence. The Adrp, Instr2 and Instr4 correspond to 1.), 2.), // and 4.) in the Scanner for Cortex-A53 errata comment above. -static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2, - uint32_t Instr4) { - if (!isADRP(Instr1)) +static bool is843419ErratumSequence(uint32_t instr1, uint32_t instr2, + uint32_t instr4) { + if (!isADRP(instr1)) return false; - uint32_t Rn = getRt(Instr1); - return isLoadStoreClass(Instr2) && - (isLoadStoreExclusive(Instr2) || isLoadLiteral(Instr2) || - isV8SingleRegisterNonStructureLoadStore(Instr2) || isSTP(Instr2) || - isSTNP(Instr2) || isST1(Instr2)) && - !doesLoadStoreWriteToReg(Instr2, Rn) && - isLoadStoreRegisterUnsigned(Instr4) && getRn(Instr4) == Rn; + uint32_t rn = getRt(instr1); + return isLoadStoreClass(instr2) && + (isLoadStoreExclusive(instr2) || isLoadLiteral(instr2) || + isV8SingleRegisterNonStructureLoadStore(instr2) || isSTP(instr2) || + isSTNP(instr2) || isST1(instr2)) && + !doesLoadStoreWriteToReg(instr2, rn) && + isLoadStoreRegisterUnsigned(instr4) && getRn(instr4) == rn; } // Scan the instruction sequence starting at Offset Off from the base of @@ -338,89 +338,89 @@ // instructions we've scanned. // Return the offset of the load or store instruction in IS that we want to // patch or 0 if no patch required. -static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off, - uint64_t Limit) { - uint64_t ISAddr = IS->getVA(0); +static uint64_t scanCortexA53Errata843419(InputSection *isec, uint64_t &off, + uint64_t limit) { + uint64_t isecAddr = isec->getVA(0); // Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8. - uint64_t InitialPageOff = (ISAddr + Off) & 0xfff; - if (InitialPageOff < 0xff8) - Off += 0xff8 - InitialPageOff; + uint64_t initialPageOff = (isecAddr + off) & 0xfff; + if (initialPageOff < 0xff8) + off += 0xff8 - initialPageOff; - bool OptionalAllowed = Limit - Off > 12; - if (Off >= Limit || Limit - Off < 12) { + bool optionalAllowed = limit - off > 12; + if (off >= limit || limit - off < 12) { // Need at least 3 4-byte sized instructions to trigger erratum. - Off = Limit; + off = limit; return 0; } - uint64_t PatchOff = 0; - const uint8_t *Buf = IS->data().begin(); - const ulittle32_t *InstBuf = reinterpret_cast(Buf + Off); - uint32_t Instr1 = *InstBuf++; - uint32_t Instr2 = *InstBuf++; - uint32_t Instr3 = *InstBuf++; - if (is843419ErratumSequence(Instr1, Instr2, Instr3)) { - PatchOff = Off + 8; - } else if (OptionalAllowed && !isBranch(Instr3)) { - uint32_t Instr4 = *InstBuf++; - if (is843419ErratumSequence(Instr1, Instr2, Instr4)) - PatchOff = Off + 12; + uint64_t patchOff = 0; + const uint8_t *buf = isec->data().begin(); + const ulittle32_t *instBuf = reinterpret_cast(buf + off); + uint32_t instr1 = *instBuf++; + uint32_t instr2 = *instBuf++; + uint32_t instr3 = *instBuf++; + if (is843419ErratumSequence(instr1, instr2, instr3)) { + patchOff = off + 8; + } else if (optionalAllowed && !isBranch(instr3)) { + uint32_t instr4 = *instBuf++; + if (is843419ErratumSequence(instr1, instr2, instr4)) + patchOff = off + 12; } - if (((ISAddr + Off) & 0xfff) == 0xff8) - Off += 4; + if (((isecAddr + off) & 0xfff) == 0xff8) + off += 4; else - Off += 0xffc; - return PatchOff; + off += 0xffc; + return patchOff; } class lld::elf::Patch843419Section : public SyntheticSection { public: - Patch843419Section(InputSection *P, uint64_t Off); + Patch843419Section(InputSection *p, uint64_t off); - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; size_t getSize() const override { return 8; } uint64_t getLDSTAddr() const; // The Section we are patching. - const InputSection *Patchee; + const InputSection *patchee; // The offset of the instruction in the Patchee section we are patching. - uint64_t PatcheeOffset; + uint64_t patcheeOffset; // A label for the start of the Patch that we can use as a relocation target. - Symbol *PatchSym; + Symbol *patchSym; }; -lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off) +lld::elf::Patch843419Section::Patch843419Section(InputSection *p, uint64_t off) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4, ".text.patch"), - Patchee(P), PatcheeOffset(Off) { - this->Parent = P->getParent(); - PatchSym = addSyntheticLocal( + patchee(p), patcheeOffset(off) { + this->parent = p->getParent(); + patchSym = addSyntheticLocal( Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0, getSize(), *this); addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this); } uint64_t lld::elf::Patch843419Section::getLDSTAddr() const { - return Patchee->getVA(PatcheeOffset); + return patchee->getVA(patcheeOffset); } -void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) { +void lld::elf::Patch843419Section::writeTo(uint8_t *buf) { // Copy the instruction that we will be replacing with a branch in the // Patchee Section. - write32le(Buf, read32le(Patchee->data().begin() + PatcheeOffset)); + write32le(buf, read32le(patchee->data().begin() + patcheeOffset)); // Apply any relocation transferred from the original PatcheeSection. // For a SyntheticSection Buf already has OutSecOff added, but relocateAlloc // also adds OutSecOff so we need to subtract to avoid double counting. - this->relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + getSize()); + this->relocateAlloc(buf - outSecOff, buf - outSecOff + getSize()); // Return address is the next instruction after the one we have just copied. - uint64_t S = getLDSTAddr() + 4; - uint64_t P = PatchSym->getVA() + 4; - Target->relocateOne(Buf + 4, R_AARCH64_JUMP26, S - P); + uint64_t s = getLDSTAddr() + 4; + uint64_t p = patchSym->getVA() + 4; + target->relocateOne(buf + 4, R_AARCH64_JUMP26, s - p); } void AArch64Err843419Patcher::init() { @@ -434,47 +434,47 @@ // within sections. If there is no next symbol then the half open interval is // [Symbol Value, End of section). The type, code or data, is determined by // the mapping symbol name, $x for code, $d for data. - auto IsCodeMapSymbol = [](const Symbol *B) { - return B->getName() == "$x" || B->getName().startswith("$x."); + auto isCodeMapSymbol = [](const Symbol *b) { + return b->getName() == "$x" || b->getName().startswith("$x."); }; - auto IsDataMapSymbol = [](const Symbol *B) { - return B->getName() == "$d" || B->getName().startswith("$d."); + auto isDataMapSymbol = [](const Symbol *b) { + return b->getName() == "$d" || b->getName().startswith("$d."); }; // Collect mapping symbols for every executable InputSection. - for (InputFile *File : ObjectFiles) { - auto *F = cast>(File); - for (Symbol *B : F->getLocalSymbols()) { - auto *Def = dyn_cast(B); - if (!Def) + for (InputFile *file : objectFiles) { + auto *f = cast>(file); + for (Symbol *b : f->getLocalSymbols()) { + auto *def = dyn_cast(b); + if (!def) continue; - if (!IsCodeMapSymbol(Def) && !IsDataMapSymbol(Def)) + if (!isCodeMapSymbol(def) && !isDataMapSymbol(def)) continue; - if (auto *Sec = dyn_cast_or_null(Def->Section)) - if (Sec->Flags & SHF_EXECINSTR) - SectionMap[Sec].push_back(Def); + if (auto *sec = dyn_cast_or_null(def->section)) + if (sec->flags & SHF_EXECINSTR) + sectionMap[sec].push_back(def); } } // For each InputSection make sure the mapping symbols are in sorted in // ascending order and free from consecutive runs of mapping symbols with // the same type. For example we must remove the redundant $d.1 from $x.0 // $d.0 $d.1 $x.1. - for (auto &KV : SectionMap) { - std::vector &MapSyms = KV.second; - if (MapSyms.size() <= 1) + for (auto &kv : sectionMap) { + std::vector &mapSyms = kv.second; + if (mapSyms.size() <= 1) continue; - llvm::stable_sort(MapSyms, [](const Defined *A, const Defined *B) { - return A->Value < B->Value; + llvm::stable_sort(mapSyms, [](const Defined *a, const Defined *b) { + return a->value < b->value; }); - MapSyms.erase( - std::unique(MapSyms.begin(), MapSyms.end(), - [=](const Defined *A, const Defined *B) { - return (IsCodeMapSymbol(A) && IsCodeMapSymbol(B)) || - (IsDataMapSymbol(A) && IsDataMapSymbol(B)); + mapSyms.erase( + std::unique(mapSyms.begin(), mapSyms.end(), + [=](const Defined *a, const Defined *b) { + return (isCodeMapSymbol(a) && isCodeMapSymbol(b)) || + (isDataMapSymbol(a) && isDataMapSymbol(b)); }), - MapSyms.end()); + mapSyms.end()); } - Initialized = true; + initialized = true; } // Insert the PatchSections we have created back into the @@ -483,60 +483,60 @@ // executable sections, although we may need to insert them earlier if the // InputSectionDescription is larger than the maximum branch range. void AArch64Err843419Patcher::insertPatches( - InputSectionDescription &ISD, std::vector &Patches) { - uint64_t ISLimit; - uint64_t PrevISLimit = ISD.Sections.front()->OutSecOff; - uint64_t PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); - uint64_t OutSecAddr = ISD.Sections.front()->getParent()->Addr; + InputSectionDescription &isd, std::vector &patches) { + uint64_t isecLimit; + uint64_t prevISLimit = isd.sections.front()->outSecOff; + uint64_t patchUpperBound = prevISLimit + target->getThunkSectionSpacing(); + uint64_t outSecAddr = isd.sections.front()->getParent()->addr; // Set the OutSecOff of patches to the place where we want to insert them. // We use a similar strategy to Thunk placement. Place patches roughly // every multiple of maximum branch range. - auto PatchIt = Patches.begin(); - auto PatchEnd = Patches.end(); - for (const InputSection *IS : ISD.Sections) { - ISLimit = IS->OutSecOff + IS->getSize(); - if (ISLimit > PatchUpperBound) { - while (PatchIt != PatchEnd) { - if ((*PatchIt)->getLDSTAddr() - OutSecAddr >= PrevISLimit) + auto patchIt = patches.begin(); + auto patchEnd = patches.end(); + for (const InputSection *isec : isd.sections) { + isecLimit = isec->outSecOff + isec->getSize(); + if (isecLimit > patchUpperBound) { + while (patchIt != patchEnd) { + if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevISLimit) break; - (*PatchIt)->OutSecOff = PrevISLimit; - ++PatchIt; + (*patchIt)->outSecOff = prevISLimit; + ++patchIt; } - PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); + patchUpperBound = prevISLimit + target->getThunkSectionSpacing(); } - PrevISLimit = ISLimit; + prevISLimit = isecLimit; } - for (; PatchIt != PatchEnd; ++PatchIt) { - (*PatchIt)->OutSecOff = ISLimit; + for (; patchIt != patchEnd; ++patchIt) { + (*patchIt)->outSecOff = isecLimit; } // merge all patch sections. We use the OutSecOff assigned above to // determine the insertion point. This is ok as we only merge into an // InputSectionDescription once per pass, and at the end of the pass // assignAddresses() will recalculate all the OutSecOff values. - std::vector Tmp; - Tmp.reserve(ISD.Sections.size() + Patches.size()); - auto MergeCmp = [](const InputSection *A, const InputSection *B) { - if (A->OutSecOff < B->OutSecOff) + std::vector tmp; + tmp.reserve(isd.sections.size() + patches.size()); + auto mergeCmp = [](const InputSection *a, const InputSection *b) { + if (a->outSecOff < b->outSecOff) return true; - if (A->OutSecOff == B->OutSecOff && isa(A) && - !isa(B)) + if (a->outSecOff == b->outSecOff && isa(a) && + !isa(b)) return true; return false; }; - std::merge(ISD.Sections.begin(), ISD.Sections.end(), Patches.begin(), - Patches.end(), std::back_inserter(Tmp), MergeCmp); - ISD.Sections = std::move(Tmp); + std::merge(isd.sections.begin(), isd.sections.end(), patches.begin(), + patches.end(), std::back_inserter(tmp), mergeCmp); + isd.sections = std::move(tmp); } // Given an erratum sequence that starts at address AdrpAddr, with an // instruction that we need to patch at PatcheeOffset from the start of // InputSection IS, create a Patch843419 Section and add it to the // Patches that we need to insert. -static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset, - InputSection *IS, - std::vector &Patches) { +static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset, + InputSection *isec, + std::vector &patches) { // There may be a relocation at the same offset that we are patching. There // are four cases that we need to consider. // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this @@ -551,29 +551,29 @@ // and replace the relocation with a R_AARCH_JUMP26 branch relocation. // Case 4: No relocation. We must create a new R_AARCH64_JUMP26 branch // relocation at the offset. - auto RelIt = llvm::find_if(IS->Relocations, [=](const Relocation &R) { - return R.Offset == PatcheeOffset; + auto relIt = llvm::find_if(isec->relocations, [=](const Relocation &r) { + return r.offset == patcheeOffset; }); - if (RelIt != IS->Relocations.end() && - (RelIt->Type == R_AARCH64_JUMP26 || RelIt->Expr == R_RELAX_TLS_IE_TO_LE)) + if (relIt != isec->relocations.end() && + (relIt->type == R_AARCH64_JUMP26 || relIt->expr == R_RELAX_TLS_IE_TO_LE)) return; log("detected cortex-a53-843419 erratum sequence starting at " + - utohexstr(AdrpAddr) + " in unpatched output."); + utohexstr(adrpAddr) + " in unpatched output."); - auto *PS = make(IS, PatcheeOffset); - Patches.push_back(PS); + auto *ps = make(isec, patcheeOffset); + patches.push_back(ps); - auto MakeRelToPatch = [](uint64_t Offset, Symbol *PatchSym) { - return Relocation{R_PC, R_AARCH64_JUMP26, Offset, 0, PatchSym}; + auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) { + return Relocation{R_PC, R_AARCH64_JUMP26, offset, 0, patchSym}; }; - if (RelIt != IS->Relocations.end()) { - PS->Relocations.push_back( - {RelIt->Expr, RelIt->Type, 0, RelIt->Addend, RelIt->Sym}); - *RelIt = MakeRelToPatch(PatcheeOffset, PS->PatchSym); + if (relIt != isec->relocations.end()) { + ps->relocations.push_back( + {relIt->expr, relIt->type, 0, relIt->addend, relIt->sym}); + *relIt = makeRelToPatch(patcheeOffset, ps->patchSym); } else - IS->Relocations.push_back(MakeRelToPatch(PatcheeOffset, PS->PatchSym)); + isec->relocations.push_back(makeRelToPatch(patcheeOffset, ps->patchSym)); } // Scan all the instructions in InputSectionDescription, for each instance of @@ -581,40 +581,40 @@ // Patch843419Sections that need to be applied to ISD. std::vector AArch64Err843419Patcher::patchInputSectionDescription( - InputSectionDescription &ISD) { - std::vector Patches; - for (InputSection *IS : ISD.Sections) { + InputSectionDescription &isd) { + std::vector patches; + for (InputSection *isec : isd.sections) { // LLD doesn't use the erratum sequence in SyntheticSections. - if (isa(IS)) + if (isa(isec)) continue; // Use SectionMap to make sure we only scan code and not inline data. // We have already sorted MapSyms in ascending order and removed consecutive // mapping symbols of the same type. Our range of executable instructions to // scan is therefore [CodeSym->Value, DataSym->Value) or [CodeSym->Value, // section size). - std::vector &MapSyms = SectionMap[IS]; + std::vector &mapSyms = sectionMap[isec]; - auto CodeSym = llvm::find_if(MapSyms, [&](const Defined *MS) { - return MS->getName().startswith("$x"); + auto codeSym = llvm::find_if(mapSyms, [&](const Defined *ms) { + return ms->getName().startswith("$x"); }); - while (CodeSym != MapSyms.end()) { - auto DataSym = std::next(CodeSym); - uint64_t Off = (*CodeSym)->Value; - uint64_t Limit = - (DataSym == MapSyms.end()) ? IS->data().size() : (*DataSym)->Value; - - while (Off < Limit) { - uint64_t StartAddr = IS->getVA(Off); - if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit)) - implementPatch(StartAddr, PatcheeOffset, IS, Patches); + while (codeSym != mapSyms.end()) { + auto dataSym = std::next(codeSym); + uint64_t off = (*codeSym)->value; + uint64_t limit = + (dataSym == mapSyms.end()) ? isec->data().size() : (*dataSym)->value; + + while (off < limit) { + uint64_t startAddr = isec->getVA(off); + if (uint64_t patcheeOffset = scanCortexA53Errata843419(isec, off, limit)) + implementPatch(startAddr, patcheeOffset, isec, patches); } - if (DataSym == MapSyms.end()) + if (dataSym == mapSyms.end()) break; - CodeSym = std::next(DataSym); + codeSym = std::next(dataSym); } } - return Patches; + return patches; } // For each InputSectionDescription make one pass over the executable sections @@ -630,22 +630,22 @@ // Ouptut and Input Sections may have been changed. // Returns false if no patches were required and no changes were made. bool AArch64Err843419Patcher::createFixes() { - if (Initialized == false) + if (initialized == false) init(); - bool AddressesChanged = false; - for (OutputSection *OS : OutputSections) { - if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) + bool addressesChanged = false; + for (OutputSection *os : outputSections) { + if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR)) continue; - for (BaseCommand *BC : OS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) { - std::vector Patches = - patchInputSectionDescription(*ISD); - if (!Patches.empty()) { - insertPatches(*ISD, Patches); - AddressesChanged = true; + for (BaseCommand *bc : os->sectionCommands) + if (auto *isd = dyn_cast(bc)) { + std::vector patches = + patchInputSectionDescription(*isd); + if (!patches.empty()) { + insertPatches(*isd, patches); + addressesChanged = true; } } } - return AddressesChanged; + return addressesChanged; } Index: lld/trunk/ELF/Arch/AArch64.cpp =================================================================== --- lld/trunk/ELF/Arch/AArch64.cpp +++ lld/trunk/ELF/Arch/AArch64.cpp @@ -23,59 +23,59 @@ // Page(Expr) is the page address of the expression Expr, defined // as (Expr & ~0xFFF). (This applies even if the machine page size // supported by the platform has a different value.) -uint64_t elf::getAArch64Page(uint64_t Expr) { - return Expr & ~static_cast(0xFFF); +uint64_t elf::getAArch64Page(uint64_t expr) { + return expr & ~static_cast(0xFFF); } namespace { class AArch64 : public TargetInfo { public: AArch64(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const override; uint32_t getThunkSectionSpacing() const override; - bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; - bool usesOnlyLowPageBits(RelType Type) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; + bool usesOnlyLowPageBits(RelType type) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace AArch64::AArch64() { - CopyRel = R_AARCH64_COPY; - RelativeRel = R_AARCH64_RELATIVE; - IRelativeRel = R_AARCH64_IRELATIVE; - GotRel = R_AARCH64_GLOB_DAT; - NoneRel = R_AARCH64_NONE; - PltRel = R_AARCH64_JUMP_SLOT; - SymbolicRel = R_AARCH64_ABS64; - TlsDescRel = R_AARCH64_TLSDESC; - TlsGotRel = R_AARCH64_TLS_TPREL64; - PltEntrySize = 16; - PltHeaderSize = 32; - DefaultMaxPageSize = 65536; + copyRel = R_AARCH64_COPY; + relativeRel = R_AARCH64_RELATIVE; + iRelativeRel = R_AARCH64_IRELATIVE; + gotRel = R_AARCH64_GLOB_DAT; + noneRel = R_AARCH64_NONE; + pltRel = R_AARCH64_JUMP_SLOT; + symbolicRel = R_AARCH64_ABS64; + tlsDescRel = R_AARCH64_TLSDESC; + tlsGotRel = R_AARCH64_TLS_TPREL64; + pltEntrySize = 16; + pltHeaderSize = 32; + defaultMaxPageSize = 65536; // Align to the 2 MiB page size (known as a superpage or huge page). // FreeBSD automatically promotes 2 MiB-aligned allocations. - DefaultImageBase = 0x200000; + defaultImageBase = 0x200000; - NeedsThunks = true; + needsThunks = true; } -RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_AARCH64_TLSDESC_ADR_PAGE21: return R_AARCH64_TLSDESC_PAGE; case R_AARCH64_TLSDESC_LD64_LO12: @@ -117,18 +117,18 @@ } } -RelExpr AArch64::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - if (Expr == R_RELAX_TLS_GD_TO_IE) { - if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) +RelExpr AArch64::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + if (expr == R_RELAX_TLS_GD_TO_IE) { + if (type == R_AARCH64_TLSDESC_ADR_PAGE21) return R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC; return R_RELAX_TLS_GD_TO_IE_ABS; } - return Expr; + return expr; } -bool AArch64::usesOnlyLowPageBits(RelType Type) const { - switch (Type) { +bool AArch64::usesOnlyLowPageBits(RelType type) const { + switch (type) { default: return false; case R_AARCH64_ADD_ABS_LO12_NC: @@ -145,18 +145,18 @@ } } -RelType AArch64::getDynRel(RelType Type) const { - if (Type == R_AARCH64_ABS64) - return Type; +RelType AArch64::getDynRel(RelType type) const { + if (type == R_AARCH64_ABS64) + return type; return R_AARCH64_NONE; } -void AArch64::writeGotPlt(uint8_t *Buf, const Symbol &) const { - write64le(Buf, In.Plt->getVA()); +void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const { + write64le(buf, in.plt->getVA()); } -void AArch64::writePltHeader(uint8_t *Buf) const { - const uint8_t PltData[] = { +void AArch64::writePltHeader(uint8_t *buf) const { + const uint8_t pltData[] = { 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))] @@ -166,42 +166,42 @@ 0x1f, 0x20, 0x03, 0xd5, // nop 0x1f, 0x20, 0x03, 0xd5 // nop }; - memcpy(Buf, PltData, sizeof(PltData)); + memcpy(buf, pltData, sizeof(pltData)); - uint64_t Got = In.GotPlt->getVA(); - uint64_t Plt = In.Plt->getVA(); - relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, - getAArch64Page(Got + 16) - getAArch64Page(Plt + 4)); - relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16); - relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16); + uint64_t got = in.gotPlt->getVA(); + uint64_t plt = in.plt->getVA(); + relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(got + 16) - getAArch64Page(plt + 4)); + relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16); + relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16); } -void AArch64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Inst[] = { +void AArch64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t inst[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))] 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n])) 0x20, 0x02, 0x1f, 0xd6 // br x17 }; - memcpy(Buf, Inst, sizeof(Inst)); + memcpy(buf, inst, sizeof(inst)); - relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21, - getAArch64Page(GotPltEntryAddr) - getAArch64Page(PltEntryAddr)); - relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotPltEntryAddr); - relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr); + relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr)); + relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr); + relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); } -bool AArch64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { +bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { // ELF for the ARM 64-bit architecture, section Call and Jump relocations // only permits range extension thunks for R_AARCH64_CALL26 and // R_AARCH64_JUMP26 relocation types. - if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) + if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26) return false; - uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); - return !inBranchRange(Type, BranchAddr, Dst); + uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA(); + return !inBranchRange(type, branchAddr, dst); } uint32_t AArch64::getThunkSectionSpacing() const { @@ -211,70 +211,70 @@ return (128 * 1024 * 1024) - 0x30000; } -bool AArch64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { - if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) +bool AArch64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26) return true; // The AArch64 call and unconditional branch instructions have a range of // +/- 128 MiB. - uint64_t Range = 128 * 1024 * 1024; - if (Dst > Src) { + uint64_t range = 128 * 1024 * 1024; + if (dst > src) { // Immediate of branch is signed. - Range -= 4; - return Dst - Src <= Range; + range -= 4; + return dst - src <= range; } - return Src - Dst <= Range; + return src - dst <= range; } -static void write32AArch64Addr(uint8_t *L, uint64_t Imm) { - uint32_t ImmLo = (Imm & 0x3) << 29; - uint32_t ImmHi = (Imm & 0x1FFFFC) << 3; - uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3); - write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi); +static void write32AArch64Addr(uint8_t *l, uint64_t imm) { + uint32_t immLo = (imm & 0x3) << 29; + uint32_t immHi = (imm & 0x1FFFFC) << 3; + uint64_t mask = (0x3 << 29) | (0x1FFFFC << 3); + write32le(l, (read32le(l) & ~mask) | immLo | immHi); } // Return the bits [Start, End] from Val shifted Start bits. // For instance, getBits(0xF0, 4, 8) returns 0xF. -static uint64_t getBits(uint64_t Val, int Start, int End) { - uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1; - return (Val >> Start) & Mask; +static uint64_t getBits(uint64_t val, int start, int end) { + uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1; + return (val >> start) & mask; } -static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } +static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); } // Update the immediate field in a AARCH64 ldr, str, and add instruction. -static void or32AArch64Imm(uint8_t *L, uint64_t Imm) { - or32le(L, (Imm & 0xFFF) << 10); +static void or32AArch64Imm(uint8_t *l, uint64_t imm) { + or32le(l, (imm & 0xFFF) << 10); } -void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_AARCH64_ABS16: case R_AARCH64_PREL16: - checkIntUInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16le(loc, val); break; case R_AARCH64_ABS32: case R_AARCH64_PREL32: - checkIntUInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkIntUInt(loc, val, 32, type); + write32le(loc, val); break; case R_AARCH64_ABS64: case R_AARCH64_PREL64: - write64le(Loc, Val); + write64le(loc, val); break; case R_AARCH64_ADD_ABS_LO12_NC: - or32AArch64Imm(Loc, Val); + or32AArch64Imm(loc, val); break; case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_ADR_PREL_PG_HI21: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case R_AARCH64_TLSDESC_ADR_PAGE21: - checkInt(Loc, Val, 33, Type); - write32AArch64Addr(Loc, Val >> 12); + checkInt(loc, val, 33, type); + write32AArch64Addr(loc, val >> 12); break; case R_AARCH64_ADR_PREL_LO21: - checkInt(Loc, Val, 21, Type); - write32AArch64Addr(Loc, Val); + checkInt(loc, val, 21, type); + write32AArch64Addr(loc, val); break; case R_AARCH64_JUMP26: // Normally we would just write the bits of the immediate field, however @@ -284,75 +284,75 @@ // opcode and the immediate (0 001 | 01 imm26) we can do this // transformation by placing a R_AARCH64_JUMP26 relocation at the offset of // the instruction we want to patch. - write32le(Loc, 0x14000000); + write32le(loc, 0x14000000); LLVM_FALLTHROUGH; case R_AARCH64_CALL26: - checkInt(Loc, Val, 28, Type); - or32le(Loc, (Val & 0x0FFFFFFC) >> 2); + checkInt(loc, val, 28, type); + or32le(loc, (val & 0x0FFFFFFC) >> 2); break; case R_AARCH64_CONDBR19: case R_AARCH64_LD_PREL_LO19: - checkAlignment(Loc, Val, 4, Type); - checkInt(Loc, Val, 21, Type); - or32le(Loc, (Val & 0x1FFFFC) << 3); + checkAlignment(loc, val, 4, type); + checkInt(loc, val, 21, type); + or32le(loc, (val & 0x1FFFFC) << 3); break; case R_AARCH64_LDST8_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC: - or32AArch64Imm(Loc, getBits(Val, 0, 11)); + or32AArch64Imm(loc, getBits(val, 0, 11)); break; case R_AARCH64_LDST16_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC: - checkAlignment(Loc, Val, 2, Type); - or32AArch64Imm(Loc, getBits(Val, 1, 11)); + checkAlignment(loc, val, 2, type); + or32AArch64Imm(loc, getBits(val, 1, 11)); break; case R_AARCH64_LDST32_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC: - checkAlignment(Loc, Val, 4, Type); - or32AArch64Imm(Loc, getBits(Val, 2, 11)); + checkAlignment(loc, val, 4, type); + or32AArch64Imm(loc, getBits(val, 2, 11)); break; case R_AARCH64_LDST64_ABS_LO12_NC: case R_AARCH64_LD64_GOT_LO12_NC: case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC: case R_AARCH64_TLSDESC_LD64_LO12: - checkAlignment(Loc, Val, 8, Type); - or32AArch64Imm(Loc, getBits(Val, 3, 11)); + checkAlignment(loc, val, 8, type); + or32AArch64Imm(loc, getBits(val, 3, 11)); break; case R_AARCH64_LDST128_ABS_LO12_NC: case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC: - checkAlignment(Loc, Val, 16, Type); - or32AArch64Imm(Loc, getBits(Val, 4, 11)); + checkAlignment(loc, val, 16, type); + or32AArch64Imm(loc, getBits(val, 4, 11)); break; case R_AARCH64_MOVW_UABS_G0_NC: - or32le(Loc, (Val & 0xFFFF) << 5); + or32le(loc, (val & 0xFFFF) << 5); break; case R_AARCH64_MOVW_UABS_G1_NC: - or32le(Loc, (Val & 0xFFFF0000) >> 11); + or32le(loc, (val & 0xFFFF0000) >> 11); break; case R_AARCH64_MOVW_UABS_G2_NC: - or32le(Loc, (Val & 0xFFFF00000000) >> 27); + or32le(loc, (val & 0xFFFF00000000) >> 27); break; case R_AARCH64_MOVW_UABS_G3: - or32le(Loc, (Val & 0xFFFF000000000000) >> 43); + or32le(loc, (val & 0xFFFF000000000000) >> 43); break; case R_AARCH64_TSTBR14: - checkInt(Loc, Val, 16, Type); - or32le(Loc, (Val & 0xFFFC) << 3); + checkInt(loc, val, 16, type); + or32le(loc, (val & 0xFFFC) << 3); break; case R_AARCH64_TLSLE_ADD_TPREL_HI12: - checkUInt(Loc, Val, 24, Type); - or32AArch64Imm(Loc, Val >> 12); + checkUInt(loc, val, 24, type); + or32AArch64Imm(loc, val >> 12); break; case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: case R_AARCH64_TLSDESC_ADD_LO12: - or32AArch64Imm(Loc, Val); + or32AArch64Imm(loc, val); break; default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } -void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void AArch64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { // TLSDESC Global-Dynamic relocation are in the form: // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] @@ -364,25 +364,25 @@ // movk x0, #0x10 // nop // nop - checkUInt(Loc, Val, 32, Type); + checkUInt(loc, val, 32, type); - switch (Type) { + switch (type) { case R_AARCH64_TLSDESC_ADD_LO12: case R_AARCH64_TLSDESC_CALL: - write32le(Loc, 0xd503201f); // nop + write32le(loc, 0xd503201f); // nop return; case R_AARCH64_TLSDESC_ADR_PAGE21: - write32le(Loc, 0xd2a00000 | (((Val >> 16) & 0xffff) << 5)); // movz + write32le(loc, 0xd2a00000 | (((val >> 16) & 0xffff) << 5)); // movz return; case R_AARCH64_TLSDESC_LD64_LO12: - write32le(Loc, 0xf2800000 | ((Val & 0xffff) << 5)); // movk + write32le(loc, 0xf2800000 | ((val & 0xffff) << 5)); // movk return; default: llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); } } -void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void AArch64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { // TLSDESC Global-Dynamic relocation are in the form: // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21] // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12] @@ -395,37 +395,37 @@ // nop // nop - switch (Type) { + switch (type) { case R_AARCH64_TLSDESC_ADD_LO12: case R_AARCH64_TLSDESC_CALL: - write32le(Loc, 0xd503201f); // nop + write32le(loc, 0xd503201f); // nop break; case R_AARCH64_TLSDESC_ADR_PAGE21: - write32le(Loc, 0x90000000); // adrp - relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val); + write32le(loc, 0x90000000); // adrp + relocateOne(loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, val); break; case R_AARCH64_TLSDESC_LD64_LO12: - write32le(Loc, 0xf9400000); // ldr - relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val); + write32le(loc, 0xf9400000); // ldr + relocateOne(loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, val); break; default: llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); } } -void AArch64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - checkUInt(Loc, Val, 32, Type); +void AArch64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { + checkUInt(loc, val, 32, type); - if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { + if (type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) { // Generate MOVZ. - uint32_t RegNo = read32le(Loc) & 0x1f; - write32le(Loc, (0xd2a00000 | RegNo) | (((Val >> 16) & 0xffff) << 5)); + uint32_t regNo = read32le(loc) & 0x1f; + write32le(loc, (0xd2a00000 | regNo) | (((val >> 16) & 0xffff) << 5)); return; } - if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) { + if (type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) { // Generate MOVK. - uint32_t RegNo = read32le(Loc) & 0x1f; - write32le(Loc, (0xf2800000 | RegNo) | ((Val & 0xffff) << 5)); + uint32_t regNo = read32le(loc) & 0x1f; + write32le(loc, (0xf2800000 | regNo) | ((val & 0xffff) << 5)); return; } llvm_unreachable("invalid relocation for TLS IE to LE relaxation"); @@ -470,19 +470,19 @@ class AArch64BtiPac final : public AArch64 { public: AArch64BtiPac(); - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; private: - bool BtiHeader; // bti instruction needed in PLT Header - bool BtiEntry; // bti instruction needed in PLT Entry - bool PacEntry; // autia1716 instruction needed in PLT Entry + bool btiHeader; // bti instruction needed in PLT Header + bool btiEntry; // bti instruction needed in PLT Entry + bool pacEntry; // autia1716 instruction needed in PLT Entry }; } // namespace AArch64BtiPac::AArch64BtiPac() { - BtiHeader = (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI); + btiHeader = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI); // A BTI (Branch Target Indicator) Plt Entry is only required if the // address of the PLT entry can be taken by the program, which permits an // indirect jump to the PLT entry. This can happen when the address @@ -490,16 +490,16 @@ // the function in an executable being taken by a shared library. // FIXME: There is a potential optimization to omit the BTI if we detect // that the address of the PLT entry isn't taken. - BtiEntry = BtiHeader && !Config->Shared; - PacEntry = (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC); + btiEntry = btiHeader && !config->shared; + pacEntry = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC); - if (BtiEntry || PacEntry) - PltEntrySize = 24; + if (btiEntry || pacEntry) + pltEntrySize = 24; } -void AArch64BtiPac::writePltHeader(uint8_t *Buf) const { - const uint8_t BtiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c - const uint8_t PltData[] = { +void AArch64BtiPac::writePltHeader(uint8_t *buf) const { + const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c + const uint8_t pltData[] = { 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]! 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))] @@ -508,80 +508,80 @@ 0x1f, 0x20, 0x03, 0xd5, // nop 0x1f, 0x20, 0x03, 0xd5 // nop }; - const uint8_t NopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop + const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop - uint64_t Got = In.GotPlt->getVA(); - uint64_t Plt = In.Plt->getVA(); + uint64_t got = in.gotPlt->getVA(); + uint64_t plt = in.plt->getVA(); - if (BtiHeader) { + if (btiHeader) { // PltHeader is called indirectly by Plt[N]. Prefix PltData with a BTI C // instruction. - memcpy(Buf, BtiData, sizeof(BtiData)); - Buf += sizeof(BtiData); - Plt += sizeof(BtiData); - } - memcpy(Buf, PltData, sizeof(PltData)); - - relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, - getAArch64Page(Got + 16) - getAArch64Page(Plt + 8)); - relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16); - relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16); - if (!BtiHeader) + memcpy(buf, btiData, sizeof(btiData)); + buf += sizeof(btiData); + plt += sizeof(btiData); + } + memcpy(buf, pltData, sizeof(pltData)); + + relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(got + 16) - getAArch64Page(plt + 8)); + relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16); + relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16); + if (!btiHeader) // We didn't add the BTI c instruction so round out size with NOP. - memcpy(Buf + sizeof(PltData), NopData, sizeof(NopData)); + memcpy(buf + sizeof(pltData), nopData, sizeof(nopData)); } -void AArch64BtiPac::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { +void AArch64BtiPac::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { // The PLT entry is of the form: // [BtiData] AddrInst (PacBr | StdBr) [NopData] - const uint8_t BtiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c - const uint8_t AddrInst[] = { + const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c + const uint8_t addrInst[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))] 0x10, 0x02, 0x00, 0x91 // add x16, x16, Offset(&(.plt.got[n])) }; - const uint8_t PacBr[] = { + const uint8_t pacBr[] = { 0x9f, 0x21, 0x03, 0xd5, // autia1716 0x20, 0x02, 0x1f, 0xd6 // br x17 }; - const uint8_t StdBr[] = { + const uint8_t stdBr[] = { 0x20, 0x02, 0x1f, 0xd6, // br x17 0x1f, 0x20, 0x03, 0xd5 // nop }; - const uint8_t NopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop + const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop - if (BtiEntry) { - memcpy(Buf, BtiData, sizeof(BtiData)); - Buf += sizeof(BtiData); - PltEntryAddr += sizeof(BtiData); - } - - memcpy(Buf, AddrInst, sizeof(AddrInst)); - relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21, - getAArch64Page(GotPltEntryAddr) - - getAArch64Page(PltEntryAddr)); - relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotPltEntryAddr); - relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr); + if (btiEntry) { + memcpy(buf, btiData, sizeof(btiData)); + buf += sizeof(btiData); + pltEntryAddr += sizeof(btiData); + } + + memcpy(buf, addrInst, sizeof(addrInst)); + relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(gotPltEntryAddr) - + getAArch64Page(pltEntryAddr)); + relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr); + relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr); - if (PacEntry) - memcpy(Buf + sizeof(AddrInst), PacBr, sizeof(PacBr)); + if (pacEntry) + memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr)); else - memcpy(Buf + sizeof(AddrInst), StdBr, sizeof(StdBr)); - if (!BtiEntry) + memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr)); + if (!btiEntry) // We didn't add the BTI c instruction so round out size with NOP. - memcpy(Buf + sizeof(AddrInst) + sizeof(StdBr), NopData, sizeof(NopData)); + memcpy(buf + sizeof(addrInst) + sizeof(stdBr), nopData, sizeof(nopData)); } static TargetInfo *getTargetInfo() { - if (Config->AndFeatures & (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | + if (config->andFeatures & (GNU_PROPERTY_AARCH64_FEATURE_1_BTI | GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) { - static AArch64BtiPac T; - return &T; + static AArch64BtiPac t; + return &t; } - static AArch64 T; - return &T; + static AArch64 t; + return &t; } TargetInfo *elf::getAArch64TargetInfo() { return getTargetInfo(); } Index: lld/trunk/ELF/Arch/AMDGPU.cpp =================================================================== --- lld/trunk/ELF/Arch/AMDGPU.cpp +++ lld/trunk/ELF/Arch/AMDGPU.cpp @@ -25,63 +25,63 @@ public: AMDGPU(); uint32_t calcEFlags() const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; }; } // namespace AMDGPU::AMDGPU() { - RelativeRel = R_AMDGPU_RELATIVE64; - GotRel = R_AMDGPU_ABS64; - NoneRel = R_AMDGPU_NONE; - SymbolicRel = R_AMDGPU_ABS64; + relativeRel = R_AMDGPU_RELATIVE64; + gotRel = R_AMDGPU_ABS64; + noneRel = R_AMDGPU_NONE; + symbolicRel = R_AMDGPU_ABS64; } -static uint32_t getEFlags(InputFile *File) { - return cast>(File)->getObj().getHeader()->e_flags; +static uint32_t getEFlags(InputFile *file) { + return cast>(file)->getObj().getHeader()->e_flags; } uint32_t AMDGPU::calcEFlags() const { - assert(!ObjectFiles.empty()); - uint32_t Ret = getEFlags(ObjectFiles[0]); + assert(!objectFiles.empty()); + uint32_t ret = getEFlags(objectFiles[0]); // Verify that all input files have the same e_flags. - for (InputFile *F : makeArrayRef(ObjectFiles).slice(1)) { - if (Ret == getEFlags(F)) + for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + if (ret == getEFlags(f)) continue; - error("incompatible e_flags: " + toString(F)); + error("incompatible e_flags: " + toString(f)); return 0; } - return Ret; + return ret; } -void AMDGPU::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_AMDGPU_ABS32: case R_AMDGPU_GOTPCREL: case R_AMDGPU_GOTPCREL32_LO: case R_AMDGPU_REL32: case R_AMDGPU_REL32_LO: - write32le(Loc, Val); + write32le(loc, val); break; case R_AMDGPU_ABS64: case R_AMDGPU_REL64: - write64le(Loc, Val); + write64le(loc, val); break; case R_AMDGPU_GOTPCREL32_HI: case R_AMDGPU_REL32_HI: - write32le(Loc, Val >> 32); + write32le(loc, val >> 32); break; default: llvm_unreachable("unknown relocation"); } } -RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_AMDGPU_ABS32: case R_AMDGPU_ABS64: return R_ABS; @@ -95,19 +95,19 @@ case R_AMDGPU_GOTPCREL32_HI: return R_GOT_PC; default: - error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + - ") against symbol " + toString(S)); + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); return R_NONE; } } -RelType AMDGPU::getDynRel(RelType Type) const { - if (Type == R_AMDGPU_ABS64) - return Type; +RelType AMDGPU::getDynRel(RelType type) const { + if (type == R_AMDGPU_ABS64) + return type; return R_AMDGPU_NONE; } TargetInfo *elf::getAMDGPUTargetInfo() { - static AMDGPU Target; - return &Target; + static AMDGPU target; + return ⌖ } Index: lld/trunk/ELF/Arch/ARM.cpp =================================================================== --- lld/trunk/ELF/Arch/ARM.cpp +++ lld/trunk/ELF/Arch/ARM.cpp @@ -26,62 +26,62 @@ public: ARM(); uint32_t calcEFlags() const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; - int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void addPltSymbols(InputSection &IS, uint64_t Off) const override; - void addPltHeaderSymbols(InputSection &ISD) const override; - bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writeIgotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void addPltSymbols(InputSection &isec, uint64_t off) const override; + void addPltHeaderSymbols(InputSection &isd) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const override; uint32_t getThunkSectionSpacing() const override; - bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace ARM::ARM() { - CopyRel = R_ARM_COPY; - RelativeRel = R_ARM_RELATIVE; - IRelativeRel = R_ARM_IRELATIVE; - GotRel = R_ARM_GLOB_DAT; - NoneRel = R_ARM_NONE; - PltRel = R_ARM_JUMP_SLOT; - SymbolicRel = R_ARM_ABS32; - TlsGotRel = R_ARM_TLS_TPOFF32; - TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; - TlsOffsetRel = R_ARM_TLS_DTPOFF32; - GotBaseSymInGotPlt = false; - PltEntrySize = 16; - PltHeaderSize = 32; - TrapInstr = {0xd4, 0xd4, 0xd4, 0xd4}; - NeedsThunks = true; + copyRel = R_ARM_COPY; + relativeRel = R_ARM_RELATIVE; + iRelativeRel = R_ARM_IRELATIVE; + gotRel = R_ARM_GLOB_DAT; + noneRel = R_ARM_NONE; + pltRel = R_ARM_JUMP_SLOT; + symbolicRel = R_ARM_ABS32; + tlsGotRel = R_ARM_TLS_TPOFF32; + tlsModuleIndexRel = R_ARM_TLS_DTPMOD32; + tlsOffsetRel = R_ARM_TLS_DTPOFF32; + gotBaseSymInGotPlt = false; + pltEntrySize = 16; + pltHeaderSize = 32; + trapInstr = {0xd4, 0xd4, 0xd4, 0xd4}; + needsThunks = true; } uint32_t ARM::calcEFlags() const { // The ABIFloatType is used by loaders to detect the floating point calling // convention. - uint32_t ABIFloatType = 0; - if (Config->ARMVFPArgs == ARMVFPArgKind::Base || - Config->ARMVFPArgs == ARMVFPArgKind::Default) - ABIFloatType = EF_ARM_ABI_FLOAT_SOFT; - else if (Config->ARMVFPArgs == ARMVFPArgKind::VFP) - ABIFloatType = EF_ARM_ABI_FLOAT_HARD; + uint32_t abiFloatType = 0; + if (config->armVFPArgs == ARMVFPArgKind::Base || + config->armVFPArgs == ARMVFPArgKind::Default) + abiFloatType = EF_ARM_ABI_FLOAT_SOFT; + else if (config->armVFPArgs == ARMVFPArgKind::VFP) + abiFloatType = EF_ARM_ABI_FLOAT_HARD; // We don't currently use any features incompatible with EF_ARM_EABI_VER5, // but we don't have any firm guarantees of conformance. Linux AArch64 // kernels (as of 2016) require an EABI version to be set. - return EF_ARM_EABI_VER5 | ABIFloatType; + return EF_ARM_EABI_VER5 | abiFloatType; } -RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr ARM::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_ARM_THM_JUMP11: return R_PC; case R_ARM_CALL: @@ -106,11 +106,11 @@ case R_ARM_SBREL32: return R_ARM_SBREL; case R_ARM_TARGET1: - return Config->Target1Rel ? R_PC : R_ABS; + return config->target1Rel ? R_PC : R_ABS; case R_ARM_TARGET2: - if (Config->Target2 == Target2Policy::Rel) + if (config->target2 == Target2Policy::Rel) return R_PC; - if (Config->Target2 == Target2Policy::Abs) + if (config->target2 == Target2Policy::Abs) return R_ABS; return R_GOT_PC; case R_ARM_TLS_GD32: @@ -143,25 +143,25 @@ } } -RelType ARM::getDynRel(RelType Type) const { - if ((Type == R_ARM_ABS32) || (Type == R_ARM_TARGET1 && !Config->Target1Rel)) +RelType ARM::getDynRel(RelType type) const { + if ((type == R_ARM_ABS32) || (type == R_ARM_TARGET1 && !config->target1Rel)) return R_ARM_ABS32; return R_ARM_NONE; } -void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const { - write32le(Buf, In.Plt->getVA()); +void ARM::writeGotPlt(uint8_t *buf, const Symbol &) const { + write32le(buf, in.plt->getVA()); } -void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { +void ARM::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An ARM entry is the address of the ifunc resolver function. - write32le(Buf, S.getVA()); + write32le(buf, s.getVA()); } // Long form PLT Header that does not have any restrictions on the displacement // of the .plt from the .plt.got. -static void writePltHeaderLong(uint8_t *Buf) { - const uint8_t PltData[] = { +static void writePltHeaderLong(uint8_t *buf) { + const uint8_t pltData[] = { 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]! 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr @@ -170,128 +170,128 @@ 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary 0xd4, 0xd4, 0xd4, 0xd4}; - memcpy(Buf, PltData, sizeof(PltData)); - uint64_t GotPlt = In.GotPlt->getVA(); - uint64_t L1 = In.Plt->getVA() + 8; - write32le(Buf + 16, GotPlt - L1 - 8); + memcpy(buf, pltData, sizeof(pltData)); + uint64_t gotPlt = in.gotPlt->getVA(); + uint64_t l1 = in.plt->getVA() + 8; + write32le(buf + 16, gotPlt - l1 - 8); } // The default PLT header requires the .plt.got to be within 128 Mb of the // .plt in the positive direction. -void ARM::writePltHeader(uint8_t *Buf) const { +void ARM::writePltHeader(uint8_t *buf) const { // Use a similar sequence to that in writePlt(), the difference is the calling // conventions mean we use lr instead of ip. The PLT entry is responsible for // saving lr on the stack, the dynamic loader is responsible for reloading // it. - const uint32_t PltData[] = { + const uint32_t pltData[] = { 0xe52de004, // L1: str lr, [sp,#-4]! 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4) 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4) 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4) }; - uint64_t Offset = In.GotPlt->getVA() - In.Plt->getVA() - 4; - if (!llvm::isUInt<27>(Offset)) { + uint64_t offset = in.gotPlt->getVA() - in.plt->getVA() - 4; + if (!llvm::isUInt<27>(offset)) { // We cannot encode the Offset, use the long form. - writePltHeaderLong(Buf); + writePltHeaderLong(buf); return; } - write32le(Buf + 0, PltData[0]); - write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff)); - write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff)); - write32le(Buf + 12, PltData[3] | (Offset & 0xfff)); - memcpy(Buf + 16, TrapInstr.data(), 4); // Pad to 32-byte boundary - memcpy(Buf + 20, TrapInstr.data(), 4); - memcpy(Buf + 24, TrapInstr.data(), 4); - memcpy(Buf + 28, TrapInstr.data(), 4); + write32le(buf + 0, pltData[0]); + write32le(buf + 4, pltData[1] | ((offset >> 20) & 0xff)); + write32le(buf + 8, pltData[2] | ((offset >> 12) & 0xff)); + write32le(buf + 12, pltData[3] | (offset & 0xfff)); + memcpy(buf + 16, trapInstr.data(), 4); // Pad to 32-byte boundary + memcpy(buf + 20, trapInstr.data(), 4); + memcpy(buf + 24, trapInstr.data(), 4); + memcpy(buf + 28, trapInstr.data(), 4); } -void ARM::addPltHeaderSymbols(InputSection &IS) const { - addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS); - addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS); +void ARM::addPltHeaderSymbols(InputSection &isec) const { + addSyntheticLocal("$a", STT_NOTYPE, 0, 0, isec); + addSyntheticLocal("$d", STT_NOTYPE, 16, 0, isec); } // Long form PLT entries that do not have any restrictions on the displacement // of the .plt from the .plt.got. -static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) { - const uint8_t PltData[] = { +static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) { + const uint8_t pltData[] = { 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip] 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8 }; - memcpy(Buf, PltData, sizeof(PltData)); - uint64_t L1 = PltEntryAddr + 4; - write32le(Buf + 12, GotPltEntryAddr - L1 - 8); + memcpy(buf, pltData, sizeof(pltData)); + uint64_t l1 = pltEntryAddr + 4; + write32le(buf + 12, gotPltEntryAddr - l1 - 8); } // The default PLT entries require the .plt.got to be within 128 Mb of the // .plt in the positive direction. -void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { +void ARM::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { // The PLT entry is similar to the example given in Appendix A of ELF for // the Arm Architecture. Instead of using the Group Relocations to find the // optimal rotation for the 8-bit immediate used in the add instructions we // hard code the most compact rotations for simplicity. This saves a load // instruction over the long plt sequences. - const uint32_t PltData[] = { + const uint32_t pltData[] = { 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8 }; - uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8; - if (!llvm::isUInt<27>(Offset)) { + uint64_t offset = gotPltEntryAddr - pltEntryAddr - 8; + if (!llvm::isUInt<27>(offset)) { // We cannot encode the Offset, use the long form. - writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff); + writePltLong(buf, gotPltEntryAddr, pltEntryAddr, index, relOff); return; } - write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff)); - write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff)); - write32le(Buf + 8, PltData[2] | (Offset & 0xfff)); - memcpy(Buf + 12, TrapInstr.data(), 4); // Pad to 16-byte boundary + write32le(buf + 0, pltData[0] | ((offset >> 20) & 0xff)); + write32le(buf + 4, pltData[1] | ((offset >> 12) & 0xff)); + write32le(buf + 8, pltData[2] | (offset & 0xfff)); + memcpy(buf + 12, trapInstr.data(), 4); // Pad to 16-byte boundary } -void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const { - addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS); - addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS); +void ARM::addPltSymbols(InputSection &isec, uint64_t off) const { + addSyntheticLocal("$a", STT_NOTYPE, off, 0, isec); + addSyntheticLocal("$d", STT_NOTYPE, off + 12, 0, isec); } -bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { +bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { // If S is an undefined weak symbol and does not have a PLT entry then it // will be resolved as a branch to the next instruction. - if (S.isUndefWeak() && !S.isInPlt()) + if (s.isUndefWeak() && !s.isInPlt()) return false; // A state change from ARM to Thumb and vice versa must go through an // interworking thunk if the relocation type is not R_ARM_CALL or // R_ARM_THM_CALL. - switch (Type) { + switch (type) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: // Source is ARM, all PLT entries are ARM so no interworking required. // Otherwise we need to interwork if Symbol has bit 0 set (Thumb). - if (Expr == R_PC && ((S.getVA() & 1) == 1)) + if (expr == R_PC && ((s.getVA() & 1) == 1)) return true; LLVM_FALLTHROUGH; case R_ARM_CALL: { - uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); - return !inBranchRange(Type, BranchAddr, Dst); + uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA(); + return !inBranchRange(type, branchAddr, dst); } case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: // Source is Thumb, all PLT entries are ARM so interworking is required. // Otherwise we need to interwork if Symbol has bit 0 clear (ARM). - if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0)) + if (expr == R_PLT_PC || ((s.getVA() & 1) == 0)) return true; LLVM_FALLTHROUGH; case R_ARM_THM_CALL: { - uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA(); - return !inBranchRange(Type, BranchAddr, Dst); + uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA(); + return !inBranchRange(type, branchAddr, dst); } } return false; @@ -327,55 +327,55 @@ // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except // ARMv6T2) the range is +/- 4MiB. - return (Config->ARMJ1J2BranchEncoding) ? 0x1000000 - 0x30000 + return (config->armJ1J2BranchEncoding) ? 0x1000000 - 0x30000 : 0x400000 - 0x7500; } -bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { - uint64_t Range; - uint64_t InstrSize; +bool ARM::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + uint64_t range; + uint64_t instrSize; - switch (Type) { + switch (type) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: - Range = 0x2000000; - InstrSize = 4; + range = 0x2000000; + instrSize = 4; break; case R_ARM_THM_JUMP19: - Range = 0x100000; - InstrSize = 2; + range = 0x100000; + instrSize = 2; break; case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - Range = Config->ARMJ1J2BranchEncoding ? 0x1000000 : 0x400000; - InstrSize = 2; + range = config->armJ1J2BranchEncoding ? 0x1000000 : 0x400000; + instrSize = 2; break; default: return true; } // PC at Src is 2 instructions ahead, immediate of branch is signed - if (Src > Dst) - Range -= 2 * InstrSize; + if (src > dst) + range -= 2 * instrSize; else - Range += InstrSize; + range += instrSize; - if ((Dst & 0x1) == 0) + if ((dst & 0x1) == 0) // Destination is ARM, if ARM caller then Src is already 4-byte aligned. // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure // destination will be 4 byte aligned. - Src &= ~0x3; + src &= ~0x3; else // Bit 0 == 1 denotes Thumb state, it is not part of the range - Dst &= ~0x1; + dst &= ~0x1; - uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src; - return Distance <= Range; + uint64_t distance = (src > dst) ? src - dst : dst - src; + return distance <= range; } -void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_ARM_ABS32: case R_ARM_BASE_PREL: case R_ARM_GOTOFF32: @@ -393,132 +393,132 @@ case R_ARM_TLS_LE32: case R_ARM_TLS_TPOFF32: case R_ARM_TLS_DTPOFF32: - write32le(Loc, Val); + write32le(loc, val); break; case R_ARM_PREL31: - checkInt(Loc, Val, 31, Type); - write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000)); + checkInt(loc, val, 31, type); + write32le(loc, (read32le(loc) & 0x80000000) | (val & ~0x80000000)); break; case R_ARM_CALL: // R_ARM_CALL is used for BL and BLX instructions, depending on the // value of bit 0 of Val, we must select a BL or BLX instruction - if (Val & 1) { + if (val & 1) { // If bit 0 of Val is 1 the target is Thumb, we must select a BLX. // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1' - checkInt(Loc, Val, 26, Type); - write32le(Loc, 0xfa000000 | // opcode - ((Val & 2) << 23) | // H - ((Val >> 2) & 0x00ffffff)); // imm24 + checkInt(loc, val, 26, type); + write32le(loc, 0xfa000000 | // opcode + ((val & 2) << 23) | // H + ((val >> 2) & 0x00ffffff)); // imm24 break; } - if ((read32le(Loc) & 0xfe000000) == 0xfa000000) + if ((read32le(loc) & 0xfe000000) == 0xfa000000) // BLX (always unconditional) instruction to an ARM Target, select an // unconditional BL. - write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff)); + write32le(loc, 0xeb000000 | (read32le(loc) & 0x00ffffff)); // fall through as BL encoding is shared with B LLVM_FALLTHROUGH; case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: - checkInt(Loc, Val, 26, Type); - write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff)); + checkInt(loc, val, 26, type); + write32le(loc, (read32le(loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff)); break; case R_ARM_THM_JUMP11: - checkInt(Loc, Val, 12, Type); - write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff)); + checkInt(loc, val, 12, type); + write16le(loc, (read32le(loc) & 0xf800) | ((val >> 1) & 0x07ff)); break; case R_ARM_THM_JUMP19: // Encoding T3: Val = S:J2:J1:imm6:imm11:0 - checkInt(Loc, Val, 21, Type); - write16le(Loc, - (read16le(Loc) & 0xfbc0) | // opcode cond - ((Val >> 10) & 0x0400) | // S - ((Val >> 12) & 0x003f)); // imm6 - write16le(Loc + 2, + checkInt(loc, val, 21, type); + write16le(loc, + (read16le(loc) & 0xfbc0) | // opcode cond + ((val >> 10) & 0x0400) | // S + ((val >> 12) & 0x003f)); // imm6 + write16le(loc + 2, 0x8000 | // opcode - ((Val >> 8) & 0x0800) | // J2 - ((Val >> 5) & 0x2000) | // J1 - ((Val >> 1) & 0x07ff)); // imm11 + ((val >> 8) & 0x0800) | // J2 + ((val >> 5) & 0x2000) | // J1 + ((val >> 1) & 0x07ff)); // imm11 break; case R_ARM_THM_CALL: // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the // value of bit 0 of Val, we must select a BL or BLX instruction - if ((Val & 1) == 0) { + if ((val & 1) == 0) { // Ensure BLX destination is 4-byte aligned. As BLX instruction may // only be two byte aligned. This must be done before overflow check - Val = alignTo(Val, 4); + val = alignTo(val, 4); } // Bit 12 is 0 for BLX, 1 for BL - write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); - if (!Config->ARMJ1J2BranchEncoding) { + write16le(loc + 2, (read16le(loc + 2) & ~0x1000) | (val & 1) << 12); + if (!config->armJ1J2BranchEncoding) { // Older Arm architectures do not support R_ARM_THM_JUMP24 and have // different encoding rules and range due to J1 and J2 always being 1. - checkInt(Loc, Val, 23, Type); - write16le(Loc, + checkInt(loc, val, 23, type); + write16le(loc, 0xf000 | // opcode - ((Val >> 12) & 0x07ff)); // imm11 - write16le(Loc + 2, - (read16le(Loc + 2) & 0xd000) | // opcode + ((val >> 12) & 0x07ff)); // imm11 + write16le(loc + 2, + (read16le(loc + 2) & 0xd000) | // opcode 0x2800 | // J1 == J2 == 1 - ((Val >> 1) & 0x07ff)); // imm11 + ((val >> 1) & 0x07ff)); // imm11 break; } // Fall through as rest of encoding is the same as B.W LLVM_FALLTHROUGH; case R_ARM_THM_JUMP24: // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 - checkInt(Loc, Val, 25, Type); - write16le(Loc, + checkInt(loc, val, 25, type); + write16le(loc, 0xf000 | // opcode - ((Val >> 14) & 0x0400) | // S - ((Val >> 12) & 0x03ff)); // imm10 - write16le(Loc + 2, - (read16le(Loc + 2) & 0xd000) | // opcode - (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1 - (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2 - ((Val >> 1) & 0x07ff)); // imm11 + ((val >> 14) & 0x0400) | // S + ((val >> 12) & 0x03ff)); // imm10 + write16le(loc + 2, + (read16le(loc + 2) & 0xd000) | // opcode + (((~(val >> 10)) ^ (val >> 11)) & 0x2000) | // J1 + (((~(val >> 11)) ^ (val >> 13)) & 0x0800) | // J2 + ((val >> 1) & 0x07ff)); // imm11 break; case R_ARM_MOVW_ABS_NC: case R_ARM_MOVW_PREL_NC: - write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) | - (Val & 0x0fff)); + write32le(loc, (read32le(loc) & ~0x000f0fff) | ((val & 0xf000) << 4) | + (val & 0x0fff)); break; case R_ARM_MOVT_ABS: case R_ARM_MOVT_PREL: - write32le(Loc, (read32le(Loc) & ~0x000f0fff) | - (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); + write32le(loc, (read32le(loc) & ~0x000f0fff) | + (((val >> 16) & 0xf000) << 4) | ((val >> 16) & 0xfff)); break; case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVT_PREL: // Encoding T1: A = imm4:i:imm3:imm8 - write16le(Loc, + write16le(loc, 0xf2c0 | // opcode - ((Val >> 17) & 0x0400) | // i - ((Val >> 28) & 0x000f)); // imm4 - write16le(Loc + 2, - (read16le(Loc + 2) & 0x8f00) | // opcode - ((Val >> 12) & 0x7000) | // imm3 - ((Val >> 16) & 0x00ff)); // imm8 + ((val >> 17) & 0x0400) | // i + ((val >> 28) & 0x000f)); // imm4 + write16le(loc + 2, + (read16le(loc + 2) & 0x8f00) | // opcode + ((val >> 12) & 0x7000) | // imm3 + ((val >> 16) & 0x00ff)); // imm8 break; case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVW_PREL_NC: // Encoding T3: A = imm4:i:imm3:imm8 - write16le(Loc, + write16le(loc, 0xf240 | // opcode - ((Val >> 1) & 0x0400) | // i - ((Val >> 12) & 0x000f)); // imm4 - write16le(Loc + 2, - (read16le(Loc + 2) & 0x8f00) | // opcode - ((Val << 4) & 0x7000) | // imm3 - (Val & 0x00ff)); // imm8 + ((val >> 1) & 0x0400) | // i + ((val >> 12) & 0x000f)); // imm4 + write16le(loc + 2, + (read16le(loc + 2) & 0x8f00) | // opcode + ((val << 4) & 0x7000) | // imm3 + (val & 0x00ff)); // imm8 break; default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } -int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const { - switch (Type) { +int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { default: return 0; case R_ARM_ABS32: @@ -534,47 +534,47 @@ case R_ARM_TLS_LDO32: case R_ARM_TLS_IE32: case R_ARM_TLS_LE32: - return SignExtend64<32>(read32le(Buf)); + return SignExtend64<32>(read32le(buf)); case R_ARM_PREL31: - return SignExtend64<31>(read32le(Buf)); + return SignExtend64<31>(read32le(buf)); case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: case R_ARM_PLT32: - return SignExtend64<26>(read32le(Buf) << 2); + return SignExtend64<26>(read32le(buf) << 2); case R_ARM_THM_JUMP11: - return SignExtend64<12>(read16le(Buf) << 1); + return SignExtend64<12>(read16le(buf) << 1); case R_ARM_THM_JUMP19: { // Encoding T3: A = S:J2:J1:imm10:imm6:0 - uint16_t Hi = read16le(Buf); - uint16_t Lo = read16le(Buf + 2); - return SignExtend64<20>(((Hi & 0x0400) << 10) | // S - ((Lo & 0x0800) << 8) | // J2 - ((Lo & 0x2000) << 5) | // J1 - ((Hi & 0x003f) << 12) | // imm6 - ((Lo & 0x07ff) << 1)); // imm11:0 + uint16_t hi = read16le(buf); + uint16_t lo = read16le(buf + 2); + return SignExtend64<20>(((hi & 0x0400) << 10) | // S + ((lo & 0x0800) << 8) | // J2 + ((lo & 0x2000) << 5) | // J1 + ((hi & 0x003f) << 12) | // imm6 + ((lo & 0x07ff) << 1)); // imm11:0 } case R_ARM_THM_CALL: - if (!Config->ARMJ1J2BranchEncoding) { + if (!config->armJ1J2BranchEncoding) { // Older Arm architectures do not support R_ARM_THM_JUMP24 and have // different encoding rules and range due to J1 and J2 always being 1. - uint16_t Hi = read16le(Buf); - uint16_t Lo = read16le(Buf + 2); - return SignExtend64<22>(((Hi & 0x7ff) << 12) | // imm11 - ((Lo & 0x7ff) << 1)); // imm11:0 + uint16_t hi = read16le(buf); + uint16_t lo = read16le(buf + 2); + return SignExtend64<22>(((hi & 0x7ff) << 12) | // imm11 + ((lo & 0x7ff) << 1)); // imm11:0 break; } LLVM_FALLTHROUGH; case R_ARM_THM_JUMP24: { // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) - uint16_t Hi = read16le(Buf); - uint16_t Lo = read16le(Buf + 2); - return SignExtend64<24>(((Hi & 0x0400) << 14) | // S - (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1 - (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2 - ((Hi & 0x003ff) << 12) | // imm0 - ((Lo & 0x007ff) << 1)); // imm11:0 + uint16_t hi = read16le(buf); + uint16_t lo = read16le(buf + 2); + return SignExtend64<24>(((hi & 0x0400) << 14) | // S + (~((lo ^ (hi << 3)) << 10) & 0x00800000) | // I1 + (~((lo ^ (hi << 1)) << 11) & 0x00400000) | // I2 + ((hi & 0x003ff) << 12) | // imm0 + ((lo & 0x007ff) << 1)); // imm11:0 } // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and // MOVT is in the range -32768 <= A < 32768 @@ -582,25 +582,25 @@ case R_ARM_MOVT_ABS: case R_ARM_MOVW_PREL_NC: case R_ARM_MOVT_PREL: { - uint64_t Val = read32le(Buf) & 0x000f0fff; - return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff)); + uint64_t val = read32le(buf) & 0x000f0fff; + return SignExtend64<16>(((val & 0x000f0000) >> 4) | (val & 0x00fff)); } case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: { // Encoding T3: A = imm4:i:imm3:imm8 - uint16_t Hi = read16le(Buf); - uint16_t Lo = read16le(Buf + 2); - return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4 - ((Hi & 0x0400) << 1) | // i - ((Lo & 0x7000) >> 4) | // imm3 - (Lo & 0x00ff)); // imm8 + uint16_t hi = read16le(buf); + uint16_t lo = read16le(buf + 2); + return SignExtend64<16>(((hi & 0x000f) << 12) | // imm4 + ((hi & 0x0400) << 1) | // i + ((lo & 0x7000) >> 4) | // imm3 + (lo & 0x00ff)); // imm8 } } } TargetInfo *elf::getARMTargetInfo() { - static ARM Target; - return &Target; + static ARM target; + return ⌖ } Index: lld/trunk/ELF/Arch/AVR.cpp =================================================================== --- lld/trunk/ELF/Arch/AVR.cpp +++ lld/trunk/ELF/Arch/AVR.cpp @@ -43,34 +43,34 @@ class AVR final : public TargetInfo { public: AVR(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace -AVR::AVR() { NoneRel = R_AVR_NONE; } +AVR::AVR() { noneRel = R_AVR_NONE; } -RelExpr AVR::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { +RelExpr AVR::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { return R_ABS; } -void AVR::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void AVR::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_AVR_CALL: { - uint16_t Hi = Val >> 17; - uint16_t Lo = Val >> 1; - write16le(Loc, read16le(Loc) | ((Hi >> 1) << 4) | (Hi & 1)); - write16le(Loc + 2, Lo); + uint16_t hi = val >> 17; + uint16_t lo = val >> 1; + write16le(loc, read16le(loc) | ((hi >> 1) << 4) | (hi & 1)); + write16le(loc + 2, lo); break; } default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } TargetInfo *elf::getAVRTargetInfo() { - static AVR Target; - return &Target; + static AVR target; + return ⌖ } Index: lld/trunk/ELF/Arch/Hexagon.cpp =================================================================== --- lld/trunk/ELF/Arch/Hexagon.cpp +++ lld/trunk/ELF/Arch/Hexagon.cpp @@ -27,65 +27,65 @@ public: Hexagon(); uint32_t calcEFlags() const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; } // namespace Hexagon::Hexagon() { - PltRel = R_HEX_JMP_SLOT; - RelativeRel = R_HEX_RELATIVE; - GotRel = R_HEX_GLOB_DAT; - SymbolicRel = R_HEX_32; + pltRel = R_HEX_JMP_SLOT; + relativeRel = R_HEX_RELATIVE; + gotRel = R_HEX_GLOB_DAT; + symbolicRel = R_HEX_32; // The zero'th GOT entry is reserved for the address of _DYNAMIC. The // next 3 are reserved for the dynamic loader. - GotPltHeaderEntriesNum = 4; + gotPltHeaderEntriesNum = 4; - PltEntrySize = 16; - PltHeaderSize = 32; + pltEntrySize = 16; + pltHeaderSize = 32; // Hexagon Linux uses 64K pages by default. - DefaultMaxPageSize = 0x10000; - NoneRel = R_HEX_NONE; + defaultMaxPageSize = 0x10000; + noneRel = R_HEX_NONE; } uint32_t Hexagon::calcEFlags() const { - assert(!ObjectFiles.empty()); + assert(!objectFiles.empty()); // The architecture revision must always be equal to or greater than // greatest revision in the list of inputs. - uint32_t Ret = 0; - for (InputFile *F : ObjectFiles) { - uint32_t EFlags = cast>(F)->getObj().getHeader()->e_flags; - if (EFlags > Ret) - Ret = EFlags; + uint32_t ret = 0; + for (InputFile *f : objectFiles) { + uint32_t eflags = cast>(f)->getObj().getHeader()->e_flags; + if (eflags > ret) + ret = eflags; } - return Ret; + return ret; } -static uint32_t applyMask(uint32_t Mask, uint32_t Data) { - uint32_t Result = 0; - size_t Off = 0; - - for (size_t Bit = 0; Bit != 32; ++Bit) { - uint32_t ValBit = (Data >> Off) & 1; - uint32_t MaskBit = (Mask >> Bit) & 1; - if (MaskBit) { - Result |= (ValBit << Bit); - ++Off; +static uint32_t applyMask(uint32_t mask, uint32_t data) { + uint32_t result = 0; + size_t off = 0; + + for (size_t bit = 0; bit != 32; ++bit) { + uint32_t valBit = (data >> off) & 1; + uint32_t maskBit = (mask >> bit) & 1; + if (maskBit) { + result |= (valBit << bit); + ++off; } } - return Result; + return result; } -RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_HEX_B9_PCREL: case R_HEX_B9_PCREL_X: case R_HEX_B13_PCREL: @@ -108,16 +108,16 @@ } } -static uint32_t findMaskR6(uint32_t Insn) { +static uint32_t findMaskR6(uint32_t insn) { // There are (arguably too) many relocation masks for the DSP's // R_HEX_6_X type. The table below is used to select the correct mask // for the given instruction. struct InstructionMask { - uint32_t CmpMask; - uint32_t RelocMask; + uint32_t cmpMask; + uint32_t relocMask; }; - static const InstructionMask R6[] = { + static const InstructionMask r6[] = { {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f}, {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80}, {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0}, @@ -135,124 +135,124 @@ // Duplex forms have a fixed mask and parse bits 15:14 are always // zero. Non-duplex insns will always have at least one bit set in the // parse field. - if ((0xC000 & Insn) == 0x0) + if ((0xC000 & insn) == 0x0) return 0x03f00000; - for (InstructionMask I : R6) - if ((0xff000000 & Insn) == I.CmpMask) - return I.RelocMask; + for (InstructionMask i : r6) + if ((0xff000000 & insn) == i.cmpMask) + return i.relocMask; error("unrecognized instruction for R_HEX_6 relocation: 0x" + - utohexstr(Insn)); + utohexstr(insn)); return 0; } -static uint32_t findMaskR8(uint32_t Insn) { - if ((0xff000000 & Insn) == 0xde000000) +static uint32_t findMaskR8(uint32_t insn) { + if ((0xff000000 & insn) == 0xde000000) return 0x00e020e8; - if ((0xff000000 & Insn) == 0x3c000000) + if ((0xff000000 & insn) == 0x3c000000) return 0x0000207f; return 0x00001fe0; } -static uint32_t findMaskR11(uint32_t Insn) { - if ((0xff000000 & Insn) == 0xa1000000) +static uint32_t findMaskR11(uint32_t insn) { + if ((0xff000000 & insn) == 0xa1000000) return 0x060020ff; return 0x06003fe0; } -static uint32_t findMaskR16(uint32_t Insn) { - if ((0xff000000 & Insn) == 0x48000000) +static uint32_t findMaskR16(uint32_t insn) { + if ((0xff000000 & insn) == 0x48000000) return 0x061f20ff; - if ((0xff000000 & Insn) == 0x49000000) + if ((0xff000000 & insn) == 0x49000000) return 0x061f3fe0; - if ((0xff000000 & Insn) == 0x78000000) + if ((0xff000000 & insn) == 0x78000000) return 0x00df3fe0; - if ((0xff000000 & Insn) == 0xb0000000) + if ((0xff000000 & insn) == 0xb0000000) return 0x0fe03fe0; error("unrecognized instruction for R_HEX_16_X relocation: 0x" + - utohexstr(Insn)); + utohexstr(insn)); return 0; } -static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } +static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); } -void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_HEX_NONE: break; case R_HEX_6_PCREL_X: case R_HEX_6_X: - or32le(Loc, applyMask(findMaskR6(read32le(Loc)), Val)); + or32le(loc, applyMask(findMaskR6(read32le(loc)), val)); break; case R_HEX_8_X: - or32le(Loc, applyMask(findMaskR8(read32le(Loc)), Val)); + or32le(loc, applyMask(findMaskR8(read32le(loc)), val)); break; case R_HEX_9_X: - or32le(Loc, applyMask(0x00003fe0, Val & 0x3f)); + or32le(loc, applyMask(0x00003fe0, val & 0x3f)); break; case R_HEX_10_X: - or32le(Loc, applyMask(0x00203fe0, Val & 0x3f)); + or32le(loc, applyMask(0x00203fe0, val & 0x3f)); break; case R_HEX_11_X: case R_HEX_GOT_11_X: - or32le(Loc, applyMask(findMaskR11(read32le(Loc)), Val & 0x3f)); + or32le(loc, applyMask(findMaskR11(read32le(loc)), val & 0x3f)); break; case R_HEX_12_X: - or32le(Loc, applyMask(0x000007e0, Val)); + or32le(loc, applyMask(0x000007e0, val)); break; case R_HEX_16_X: // These relocs only have 6 effective bits. case R_HEX_GOT_16_X: - or32le(Loc, applyMask(findMaskR16(read32le(Loc)), Val & 0x3f)); + or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0x3f)); break; case R_HEX_32: case R_HEX_32_PCREL: - or32le(Loc, Val); + or32le(loc, val); break; case R_HEX_32_6_X: case R_HEX_GOT_32_6_X: - or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); + or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_B9_PCREL: - or32le(Loc, applyMask(0x003000fe, Val >> 2)); + or32le(loc, applyMask(0x003000fe, val >> 2)); break; case R_HEX_B9_PCREL_X: - or32le(Loc, applyMask(0x003000fe, Val & 0x3f)); + or32le(loc, applyMask(0x003000fe, val & 0x3f)); break; case R_HEX_B13_PCREL: - or32le(Loc, applyMask(0x00202ffe, Val >> 2)); + or32le(loc, applyMask(0x00202ffe, val >> 2)); break; case R_HEX_B15_PCREL: - or32le(Loc, applyMask(0x00df20fe, Val >> 2)); + or32le(loc, applyMask(0x00df20fe, val >> 2)); break; case R_HEX_B15_PCREL_X: - or32le(Loc, applyMask(0x00df20fe, Val & 0x3f)); + or32le(loc, applyMask(0x00df20fe, val & 0x3f)); break; case R_HEX_B22_PCREL: case R_HEX_PLT_B22_PCREL: - or32le(Loc, applyMask(0x1ff3ffe, Val >> 2)); + or32le(loc, applyMask(0x1ff3ffe, val >> 2)); break; case R_HEX_B22_PCREL_X: - or32le(Loc, applyMask(0x1ff3ffe, Val & 0x3f)); + or32le(loc, applyMask(0x1ff3ffe, val & 0x3f)); break; case R_HEX_B32_PCREL_X: - or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); + or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_HI16: - or32le(Loc, applyMask(0x00c03fff, Val >> 16)); + or32le(loc, applyMask(0x00c03fff, val >> 16)); break; case R_HEX_LO16: - or32le(Loc, applyMask(0x00c03fff, Val)); + or32le(loc, applyMask(0x00c03fff, val)); break; default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); break; } } -void Hexagon::writePltHeader(uint8_t *Buf) const { - const uint8_t PltData[] = { +void Hexagon::writePltHeader(uint8_t *buf) const { + const uint8_t pltData[] = { 0x00, 0x40, 0x00, 0x00, // { immext (#0) 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn @@ -262,30 +262,30 @@ 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker 0x0c, 0xdb, 0x00, 0x54, // trap0(#0xdb) # bring plt0 into 16byte alignment }; - memcpy(Buf, PltData, sizeof(PltData)); + memcpy(buf, pltData, sizeof(pltData)); // Offset from PLT0 to the GOT. - uint64_t Off = In.GotPlt->getVA() - In.Plt->getVA(); - relocateOne(Buf, R_HEX_B32_PCREL_X, Off); - relocateOne(Buf + 4, R_HEX_6_PCREL_X, Off); + uint64_t off = in.gotPlt->getVA() - in.plt->getVA(); + relocateOne(buf, R_HEX_B32_PCREL_X, off); + relocateOne(buf + 4, R_HEX_6_PCREL_X, off); } -void Hexagon::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Inst[] = { +void Hexagon::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t inst[] = { 0x00, 0x40, 0x00, 0x00, // { immext (#0) 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) } 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14) 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 }; - memcpy(Buf, Inst, sizeof(Inst)); + memcpy(buf, inst, sizeof(inst)); - relocateOne(Buf, R_HEX_B32_PCREL_X, GotPltEntryAddr - PltEntryAddr); - relocateOne(Buf + 4, R_HEX_6_PCREL_X, GotPltEntryAddr - PltEntryAddr); + relocateOne(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr); + relocateOne(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr); } TargetInfo *elf::getHexagonTargetInfo() { - static Hexagon Target; - return &Target; + static Hexagon target; + return ⌖ } Index: lld/trunk/ELF/Arch/MSP430.cpp =================================================================== --- lld/trunk/ELF/Arch/MSP430.cpp +++ lld/trunk/ELF/Arch/MSP430.cpp @@ -33,20 +33,20 @@ class MSP430 final : public TargetInfo { public: MSP430(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace MSP430::MSP430() { // mov.b #0, r3 - TrapInstr = {0x43, 0x43, 0x43, 0x43}; + trapInstr = {0x43, 0x43, 0x43, 0x43}; } -RelExpr MSP430::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr MSP430::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_MSP430_10_PCREL: case R_MSP430_16_PCREL: case R_MSP430_16_PCREL_BYTE: @@ -59,35 +59,35 @@ } } -void MSP430::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void MSP430::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_MSP430_8: - checkIntUInt(Loc, Val, 8, Type); - *Loc = Val; + checkIntUInt(loc, val, 8, type); + *loc = val; break; case R_MSP430_16: case R_MSP430_16_PCREL: case R_MSP430_16_BYTE: case R_MSP430_16_PCREL_BYTE: - checkIntUInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16le(loc, val); break; case R_MSP430_32: - checkIntUInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkIntUInt(loc, val, 32, type); + write32le(loc, val); break; case R_MSP430_10_PCREL: { - int16_t Offset = ((int16_t)Val >> 1) - 1; - checkInt(Loc, Offset, 10, Type); - write16le(Loc, (read16le(Loc) & 0xFC00) | (Offset & 0x3FF)); + int16_t offset = ((int16_t)val >> 1) - 1; + checkInt(loc, offset, 10, type); + write16le(loc, (read16le(loc) & 0xFC00) | (offset & 0x3FF)); break; } default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } TargetInfo *elf::getMSP430TargetInfo() { - static MSP430 Target; - return &Target; + static MSP430 target; + return ⌖ } Index: lld/trunk/ELF/Arch/Mips.cpp =================================================================== --- lld/trunk/ELF/Arch/Mips.cpp +++ lld/trunk/ELF/Arch/Mips.cpp @@ -28,47 +28,47 @@ public: MIPS(); uint32_t calcEFlags() const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; - RelType getDynRel(RelType Type) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - bool usesOnlyLowPageBits(RelType Type) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + RelType getDynRel(RelType type) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + bool usesOnlyLowPageBits(RelType type) const override; }; } // namespace template MIPS::MIPS() { - GotPltHeaderEntriesNum = 2; - DefaultMaxPageSize = 65536; - GotBaseSymInGotPlt = false; - PltEntrySize = 16; - PltHeaderSize = 32; - CopyRel = R_MIPS_COPY; - NoneRel = R_MIPS_NONE; - PltRel = R_MIPS_JUMP_SLOT; - NeedsThunks = true; + gotPltHeaderEntriesNum = 2; + defaultMaxPageSize = 65536; + gotBaseSymInGotPlt = false; + pltEntrySize = 16; + pltHeaderSize = 32; + copyRel = R_MIPS_COPY; + noneRel = R_MIPS_NONE; + pltRel = R_MIPS_JUMP_SLOT; + needsThunks = true; // Set `sigrie 1` as a trap instruction. - write32(TrapInstr.data(), 0x04170001); + write32(trapInstr.data(), 0x04170001); if (ELFT::Is64Bits) { - RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; - SymbolicRel = R_MIPS_64; - TlsGotRel = R_MIPS_TLS_TPREL64; - TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; - TlsOffsetRel = R_MIPS_TLS_DTPREL64; + relativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; + symbolicRel = R_MIPS_64; + tlsGotRel = R_MIPS_TLS_TPREL64; + tlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; + tlsOffsetRel = R_MIPS_TLS_DTPREL64; } else { - RelativeRel = R_MIPS_REL32; - SymbolicRel = R_MIPS_32; - TlsGotRel = R_MIPS_TLS_TPREL32; - TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; - TlsOffsetRel = R_MIPS_TLS_DTPREL32; + relativeRel = R_MIPS_REL32; + symbolicRel = R_MIPS_32; + tlsGotRel = R_MIPS_TLS_TPREL32; + tlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; + tlsOffsetRel = R_MIPS_TLS_DTPREL32; } } @@ -77,13 +77,13 @@ } template -RelExpr MIPS::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { +RelExpr MIPS::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { // See comment in the calculateMipsRelChain. - if (ELFT::Is64Bits || Config->MipsN32Abi) - Type &= 0xff; + if (ELFT::Is64Bits || config->mipsN32Abi) + type &= 0xff; - switch (Type) { + switch (type) { case R_MIPS_JALR: case R_MICROMIPS_JALR: return R_HINT; @@ -107,9 +107,9 @@ // offset between start of function and 'gp' value which by default // equal to the start of .got section. In that case we consider these // relocations as relative. - if (&S == ElfSym::MipsGpDisp) + if (&s == ElfSym::mipsGpDisp) return R_MIPS_GOT_GP_PC; - if (&S == ElfSym::MipsLocalGp) + if (&s == ElfSym::mipsLocalGp) return R_MIPS_GOT_GP; LLVM_FALLTHROUGH; case R_MIPS_32: @@ -146,7 +146,7 @@ return R_PC; case R_MIPS_GOT16: case R_MICROMIPS_GOT16: - if (S.isLocal()) + if (s.isLocal()) return R_MIPS_GOT_LOCAL_PAGE; LLVM_FALLTHROUGH; case R_MIPS_CALL16: @@ -175,213 +175,213 @@ case R_MIPS_NONE: return R_NONE; default: - error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + - ") against symbol " + toString(S)); + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); return R_NONE; } } -template RelType MIPS::getDynRel(RelType Type) const { - if (Type == SymbolicRel) - return Type; +template RelType MIPS::getDynRel(RelType type) const { + if (type == symbolicRel) + return type; return R_MIPS_NONE; } template -void MIPS::writeGotPlt(uint8_t *Buf, const Symbol &) const { - uint64_t VA = In.Plt->getVA(); +void MIPS::writeGotPlt(uint8_t *buf, const Symbol &) const { + uint64_t va = in.plt->getVA(); if (isMicroMips()) - VA |= 1; - write32(Buf, VA); + va |= 1; + write32(buf, va); } -template static uint32_t readShuffle(const uint8_t *Loc) { +template static uint32_t readShuffle(const uint8_t *loc) { // The major opcode of a microMIPS instruction needs to appear // in the first 16-bit word (lowest address) for efficient hardware // decode so that it knows if the instruction is 16-bit or 32-bit // as early as possible. To do so, little-endian binaries keep 16-bit // words in a big-endian order. That is why we have to swap these // words to get a correct value. - uint32_t V = read32(Loc); + uint32_t v = read32(loc); if (E == support::little) - return (V << 16) | (V >> 16); - return V; + return (v << 16) | (v >> 16); + return v; } template -static void writeValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize, - uint8_t Shift) { - uint32_t Instr = read32(Loc); - uint32_t Mask = 0xffffffff >> (32 - BitsSize); - uint32_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask); - write32(Loc, Data); +static void writeValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, + uint8_t shift) { + uint32_t instr = read32(loc); + uint32_t mask = 0xffffffff >> (32 - bitsSize); + uint32_t data = (instr & ~mask) | ((v >> shift) & mask); + write32(loc, data); } template -static void writeShuffleValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize, - uint8_t Shift) { +static void writeShuffleValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, + uint8_t shift) { // See comments in readShuffle for purpose of this code. - uint16_t *Words = (uint16_t *)Loc; + uint16_t *words = (uint16_t *)loc; if (E == support::little) - std::swap(Words[0], Words[1]); + std::swap(words[0], words[1]); - writeValue(Loc, V, BitsSize, Shift); + writeValue(loc, v, bitsSize, shift); if (E == support::little) - std::swap(Words[0], Words[1]); + std::swap(words[0], words[1]); } template -static void writeMicroRelocation16(uint8_t *Loc, uint64_t V, uint8_t BitsSize, - uint8_t Shift) { - uint16_t Instr = read16(Loc); - uint16_t Mask = 0xffff >> (16 - BitsSize); - uint16_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask); - write16(Loc, Data); +static void writeMicroRelocation16(uint8_t *loc, uint64_t v, uint8_t bitsSize, + uint8_t shift) { + uint16_t instr = read16(loc); + uint16_t mask = 0xffff >> (16 - bitsSize); + uint16_t data = (instr & ~mask) | ((v >> shift) & mask); + write16(loc, data); } -template void MIPS::writePltHeader(uint8_t *Buf) const { - const endianness E = ELFT::TargetEndianness; +template void MIPS::writePltHeader(uint8_t *buf) const { + const endianness e = ELFT::TargetEndianness; if (isMicroMips()) { - uint64_t GotPlt = In.GotPlt->getVA(); - uint64_t Plt = In.Plt->getVA(); + uint64_t gotPlt = in.gotPlt->getVA(); + uint64_t plt = in.plt->getVA(); // Overwrite trap instructions written by Writer::writeTrapInstr. - memset(Buf, 0, PltHeaderSize); + memset(buf, 0, pltHeaderSize); - write16(Buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . - write16(Buf + 4, 0xff23); // lw $25, 0($3) - write16(Buf + 8, 0x0535); // subu16 $2, $2, $3 - write16(Buf + 10, 0x2525); // srl16 $2, $2, 2 - write16(Buf + 12, 0x3302); // addiu $24, $2, -2 - write16(Buf + 14, 0xfffe); - write16(Buf + 16, 0x0dff); // move $15, $31 + write16(buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . + write16(buf + 4, 0xff23); // lw $25, 0($3) + write16(buf + 8, 0x0535); // subu16 $2, $2, $3 + write16(buf + 10, 0x2525); // srl16 $2, $2, 2 + write16(buf + 12, 0x3302); // addiu $24, $2, -2 + write16(buf + 14, 0xfffe); + write16(buf + 16, 0x0dff); // move $15, $31 if (isMipsR6()) { - write16(Buf + 18, 0x0f83); // move $28, $3 - write16(Buf + 20, 0x472b); // jalrc $25 - write16(Buf + 22, 0x0c00); // nop - relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPlt - Plt); + write16(buf + 18, 0x0f83); // move $28, $3 + write16(buf + 20, 0x472b); // jalrc $25 + write16(buf + 22, 0x0c00); // nop + relocateOne(buf, R_MICROMIPS_PC19_S2, gotPlt - plt); } else { - write16(Buf + 18, 0x45f9); // jalrc $25 - write16(Buf + 20, 0x0f83); // move $28, $3 - write16(Buf + 22, 0x0c00); // nop - relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPlt - Plt); + write16(buf + 18, 0x45f9); // jalrc $25 + write16(buf + 20, 0x0f83); // move $28, $3 + write16(buf + 22, 0x0c00); // nop + relocateOne(buf, R_MICROMIPS_PC23_S2, gotPlt - plt); } return; } - if (Config->MipsN32Abi) { - write32(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) - write32(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) - write32(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) - write32(Buf + 12, 0x030ec023); // subu $24, $24, $14 - write32(Buf + 16, 0x03e07825); // move $15, $31 - write32(Buf + 20, 0x0018c082); // srl $24, $24, 2 + if (config->mipsN32Abi) { + write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) + write32(buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) + write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) + write32(buf + 12, 0x030ec023); // subu $24, $24, $14 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c082); // srl $24, $24, 2 } else if (ELFT::Is64Bits) { - write32(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) - write32(Buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) - write32(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) - write32(Buf + 12, 0x030ec023); // subu $24, $24, $14 - write32(Buf + 16, 0x03e07825); // move $15, $31 - write32(Buf + 20, 0x0018c0c2); // srl $24, $24, 3 + write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) + write32(buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) + write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) + write32(buf + 12, 0x030ec023); // subu $24, $24, $14 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c0c2); // srl $24, $24, 3 } else { - write32(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) - write32(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) - write32(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) - write32(Buf + 12, 0x031cc023); // subu $24, $24, $28 - write32(Buf + 16, 0x03e07825); // move $15, $31 - write32(Buf + 20, 0x0018c082); // srl $24, $24, 2 - } - - uint32_t JalrInst = Config->ZHazardplt ? 0x0320fc09 : 0x0320f809; - write32(Buf + 24, JalrInst); // jalr.hb $25 or jalr $25 - write32(Buf + 28, 0x2718fffe); // subu $24, $24, 2 - - uint64_t GotPlt = In.GotPlt->getVA(); - writeValue(Buf, GotPlt + 0x8000, 16, 16); - writeValue(Buf + 4, GotPlt, 16, 0); - writeValue(Buf + 8, GotPlt, 16, 0); + write32(buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) + write32(buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) + write32(buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) + write32(buf + 12, 0x031cc023); // subu $24, $24, $28 + write32(buf + 16, 0x03e07825); // move $15, $31 + write32(buf + 20, 0x0018c082); // srl $24, $24, 2 + } + + uint32_t jalrInst = config->zHazardplt ? 0x0320fc09 : 0x0320f809; + write32(buf + 24, jalrInst); // jalr.hb $25 or jalr $25 + write32(buf + 28, 0x2718fffe); // subu $24, $24, 2 + + uint64_t gotPlt = in.gotPlt->getVA(); + writeValue(buf, gotPlt + 0x8000, 16, 16); + writeValue(buf + 4, gotPlt, 16, 0); + writeValue(buf + 8, gotPlt, 16, 0); } template -void MIPS::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const endianness E = ELFT::TargetEndianness; +void MIPS::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const endianness e = ELFT::TargetEndianness; if (isMicroMips()) { // Overwrite trap instructions written by Writer::writeTrapInstr. - memset(Buf, 0, PltEntrySize); + memset(buf, 0, pltEntrySize); if (isMipsR6()) { - write16(Buf, 0x7840); // addiupc $2, (GOTPLT) - . - write16(Buf + 4, 0xff22); // lw $25, 0($2) - write16(Buf + 8, 0x0f02); // move $24, $2 - write16(Buf + 10, 0x4723); // jrc $25 / jr16 $25 - relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPltEntryAddr - PltEntryAddr); + write16(buf, 0x7840); // addiupc $2, (GOTPLT) - . + write16(buf + 4, 0xff22); // lw $25, 0($2) + write16(buf + 8, 0x0f02); // move $24, $2 + write16(buf + 10, 0x4723); // jrc $25 / jr16 $25 + relocateOne(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr); } else { - write16(Buf, 0x7900); // addiupc $2, (GOTPLT) - . - write16(Buf + 4, 0xff22); // lw $25, 0($2) - write16(Buf + 8, 0x4599); // jrc $25 / jr16 $25 - write16(Buf + 10, 0x0f02); // move $24, $2 - relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPltEntryAddr - PltEntryAddr); + write16(buf, 0x7900); // addiupc $2, (GOTPLT) - . + write16(buf + 4, 0xff22); // lw $25, 0($2) + write16(buf + 8, 0x4599); // jrc $25 / jr16 $25 + write16(buf + 10, 0x0f02); // move $24, $2 + relocateOne(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr); } return; } - uint32_t LoadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000; - uint32_t JrInst = isMipsR6() ? (Config->ZHazardplt ? 0x03200409 : 0x03200009) - : (Config->ZHazardplt ? 0x03200408 : 0x03200008); - uint32_t AddInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000; - - write32(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) - write32(Buf + 4, LoadInst); // l[wd] $25, %lo(.got.plt entry)($15) - write32(Buf + 8, JrInst); // jr $25 / jr.hb $25 - write32(Buf + 12, AddInst); // [d]addiu $24, $15, %lo(.got.plt entry) - writeValue(Buf, GotPltEntryAddr + 0x8000, 16, 16); - writeValue(Buf + 4, GotPltEntryAddr, 16, 0); - writeValue(Buf + 12, GotPltEntryAddr, 16, 0); + uint32_t loadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000; + uint32_t jrInst = isMipsR6() ? (config->zHazardplt ? 0x03200409 : 0x03200009) + : (config->zHazardplt ? 0x03200408 : 0x03200008); + uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000; + + write32(buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) + write32(buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15) + write32(buf + 8, jrInst); // jr $25 / jr.hb $25 + write32(buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry) + writeValue(buf, gotPltEntryAddr + 0x8000, 16, 16); + writeValue(buf + 4, gotPltEntryAddr, 16, 0); + writeValue(buf + 12, gotPltEntryAddr, 16, 0); } template -bool MIPS::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { +bool MIPS::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { // Any MIPS PIC code function is invoked with its address in register $t9. // So if we have a branch instruction from non-PIC code to the PIC one // we cannot make the jump directly and need to create a small stubs // to save the target function address. // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - if (Type != R_MIPS_26 && Type != R_MIPS_PC26_S2 && - Type != R_MICROMIPS_26_S1 && Type != R_MICROMIPS_PC26_S1) + if (type != R_MIPS_26 && type != R_MIPS_PC26_S2 && + type != R_MICROMIPS_26_S1 && type != R_MICROMIPS_PC26_S1) return false; - auto *F = dyn_cast_or_null>(File); - if (!F) + auto *f = dyn_cast_or_null>(file); + if (!f) return false; // If current file has PIC code, LA25 stub is not required. - if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) + if (f->getObj().getHeader()->e_flags & EF_MIPS_PIC) return false; - auto *D = dyn_cast(&S); + auto *d = dyn_cast(&s); // LA25 is required if target file has PIC code // or target symbol is a PIC symbol. - return D && isMipsPIC(D); + return d && isMipsPIC(d); } template -int64_t MIPS::getImplicitAddend(const uint8_t *Buf, RelType Type) const { - const endianness E = ELFT::TargetEndianness; - switch (Type) { +int64_t MIPS::getImplicitAddend(const uint8_t *buf, RelType type) const { + const endianness e = ELFT::TargetEndianness; + switch (type) { case R_MIPS_32: case R_MIPS_GPREL32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL32: - return SignExtend64<32>(read32(Buf)); + return SignExtend64<32>(read32(buf)); case R_MIPS_26: // FIXME (simon): If the relocation target symbol is not a PLT entry // we should use another expression for calculation: // ((A << 2) | (P & 0xf0000000)) >> 2 - return SignExtend64<28>(read32(Buf) << 2); + return SignExtend64<28>(read32(buf) << 2); case R_MIPS_GOT16: case R_MIPS_HI16: case R_MIPS_PCHI16: - return SignExtend64<16>(read32(Buf)) << 16; + return SignExtend64<16>(read32(buf)) << 16; case R_MIPS_GPREL16: case R_MIPS_LO16: case R_MIPS_PCLO16: @@ -389,54 +389,54 @@ case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_TPREL_HI16: case R_MIPS_TLS_TPREL_LO16: - return SignExtend64<16>(read32(Buf)); + return SignExtend64<16>(read32(buf)); case R_MICROMIPS_GOT16: case R_MICROMIPS_HI16: - return SignExtend64<16>(readShuffle(Buf)) << 16; + return SignExtend64<16>(readShuffle(buf)) << 16; case R_MICROMIPS_GPREL16: case R_MICROMIPS_LO16: case R_MICROMIPS_TLS_DTPREL_HI16: case R_MICROMIPS_TLS_DTPREL_LO16: case R_MICROMIPS_TLS_TPREL_HI16: case R_MICROMIPS_TLS_TPREL_LO16: - return SignExtend64<16>(readShuffle(Buf)); + return SignExtend64<16>(readShuffle(buf)); case R_MICROMIPS_GPREL7_S2: - return SignExtend64<9>(readShuffle(Buf) << 2); + return SignExtend64<9>(readShuffle(buf) << 2); case R_MIPS_PC16: - return SignExtend64<18>(read32(Buf) << 2); + return SignExtend64<18>(read32(buf) << 2); case R_MIPS_PC19_S2: - return SignExtend64<21>(read32(Buf) << 2); + return SignExtend64<21>(read32(buf) << 2); case R_MIPS_PC21_S2: - return SignExtend64<23>(read32(Buf) << 2); + return SignExtend64<23>(read32(buf) << 2); case R_MIPS_PC26_S2: - return SignExtend64<28>(read32(Buf) << 2); + return SignExtend64<28>(read32(buf) << 2); case R_MIPS_PC32: - return SignExtend64<32>(read32(Buf)); + return SignExtend64<32>(read32(buf)); case R_MICROMIPS_26_S1: - return SignExtend64<27>(readShuffle(Buf) << 1); + return SignExtend64<27>(readShuffle(buf) << 1); case R_MICROMIPS_PC7_S1: - return SignExtend64<8>(read16(Buf) << 1); + return SignExtend64<8>(read16(buf) << 1); case R_MICROMIPS_PC10_S1: - return SignExtend64<11>(read16(Buf) << 1); + return SignExtend64<11>(read16(buf) << 1); case R_MICROMIPS_PC16_S1: - return SignExtend64<17>(readShuffle(Buf) << 1); + return SignExtend64<17>(readShuffle(buf) << 1); case R_MICROMIPS_PC18_S3: - return SignExtend64<21>(readShuffle(Buf) << 3); + return SignExtend64<21>(readShuffle(buf) << 3); case R_MICROMIPS_PC19_S2: - return SignExtend64<21>(readShuffle(Buf) << 2); + return SignExtend64<21>(readShuffle(buf) << 2); case R_MICROMIPS_PC21_S1: - return SignExtend64<22>(readShuffle(Buf) << 1); + return SignExtend64<22>(readShuffle(buf) << 1); case R_MICROMIPS_PC23_S2: - return SignExtend64<25>(readShuffle(Buf) << 2); + return SignExtend64<25>(readShuffle(buf) << 2); case R_MICROMIPS_PC26_S1: - return SignExtend64<27>(readShuffle(Buf) << 1); + return SignExtend64<27>(readShuffle(buf) << 1); default: return 0; } } static std::pair -calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) { +calculateMipsRelChain(uint8_t *loc, RelType type, uint64_t val) { // MIPS N64 ABI packs multiple relocations into the single relocation // record. In general, all up to three relocations can have arbitrary // types. In fact, Clang and GCC uses only a few combinations. For now, @@ -449,57 +449,57 @@ // relocations used to modify result of the first one: extend it to // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf - RelType Type2 = (Type >> 8) & 0xff; - RelType Type3 = (Type >> 16) & 0xff; - if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE) - return std::make_pair(Type, Val); - if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE) - return std::make_pair(Type2, Val); - if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) - return std::make_pair(Type3, -Val); - error(getErrorLocation(Loc) + "unsupported relocations combination " + - Twine(Type)); - return std::make_pair(Type & 0xff, Val); -} - -static bool isBranchReloc(RelType Type) { - return Type == R_MIPS_26 || Type == R_MIPS_PC26_S2 || - Type == R_MIPS_PC21_S2 || Type == R_MIPS_PC16; -} - -static bool isMicroBranchReloc(RelType Type) { - return Type == R_MICROMIPS_26_S1 || Type == R_MICROMIPS_PC16_S1 || - Type == R_MICROMIPS_PC10_S1 || Type == R_MICROMIPS_PC7_S1; + RelType type2 = (type >> 8) & 0xff; + RelType type3 = (type >> 16) & 0xff; + if (type2 == R_MIPS_NONE && type3 == R_MIPS_NONE) + return std::make_pair(type, val); + if (type2 == R_MIPS_64 && type3 == R_MIPS_NONE) + return std::make_pair(type2, val); + if (type2 == R_MIPS_SUB && (type3 == R_MIPS_HI16 || type3 == R_MIPS_LO16)) + return std::make_pair(type3, -val); + error(getErrorLocation(loc) + "unsupported relocations combination " + + Twine(type)); + return std::make_pair(type & 0xff, val); +} + +static bool isBranchReloc(RelType type) { + return type == R_MIPS_26 || type == R_MIPS_PC26_S2 || + type == R_MIPS_PC21_S2 || type == R_MIPS_PC16; +} + +static bool isMicroBranchReloc(RelType type) { + return type == R_MICROMIPS_26_S1 || type == R_MICROMIPS_PC16_S1 || + type == R_MICROMIPS_PC10_S1 || type == R_MICROMIPS_PC7_S1; } template -static uint64_t fixupCrossModeJump(uint8_t *Loc, RelType Type, uint64_t Val) { +static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { // Here we need to detect jump/branch from regular MIPS code // to a microMIPS target and vice versa. In that cases jump // instructions need to be replaced by their "cross-mode" // equivalents. - const endianness E = ELFT::TargetEndianness; - bool IsMicroTgt = Val & 0x1; - bool IsCrossJump = (IsMicroTgt && isBranchReloc(Type)) || - (!IsMicroTgt && isMicroBranchReloc(Type)); - if (!IsCrossJump) - return Val; + const endianness e = ELFT::TargetEndianness; + bool isMicroTgt = val & 0x1; + bool isCrossJump = (isMicroTgt && isBranchReloc(type)) || + (!isMicroTgt && isMicroBranchReloc(type)); + if (!isCrossJump) + return val; - switch (Type) { + switch (type) { case R_MIPS_26: { - uint32_t Inst = read32(Loc) >> 26; - if (Inst == 0x3 || Inst == 0x1d) { // JAL or JALX - writeValue(Loc, 0x1d << 26, 32, 0); - return Val; + uint32_t inst = read32(loc) >> 26; + if (inst == 0x3 || inst == 0x1d) { // JAL or JALX + writeValue(loc, 0x1d << 26, 32, 0); + return val; } break; } case R_MICROMIPS_26_S1: { - uint32_t Inst = readShuffle(Loc) >> 26; - if (Inst == 0x3d || Inst == 0x3c) { // JAL32 or JALX32 - Val >>= 1; - writeShuffleValue(Loc, 0x3c << 26, 32, 0); - return Val; + uint32_t inst = readShuffle(loc) >> 26; + if (inst == 0x3d || inst == 0x3c) { // JAL32 or JALX32 + val >>= 1; + writeShuffleValue(loc, 0x3c << 26, 32, 0); + return val; } break; } @@ -515,68 +515,68 @@ llvm_unreachable("unexpected jump/branch relocation"); } - error(getErrorLocation(Loc) + + error(getErrorLocation(loc) + "unsupported jump/branch instruction between ISA modes referenced by " + - toString(Type) + " relocation"); - return Val; + toString(type) + " relocation"); + return val; } template -void MIPS::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - const endianness E = ELFT::TargetEndianness; +void MIPS::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + const endianness e = ELFT::TargetEndianness; - if (ELFT::Is64Bits || Config->MipsN32Abi) - std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); + if (ELFT::Is64Bits || config->mipsN32Abi) + std::tie(type, val) = calculateMipsRelChain(loc, type, val); // Detect cross-mode jump/branch and fix instruction. - Val = fixupCrossModeJump(Loc, Type, Val); + val = fixupCrossModeJump(loc, type, val); // Thread pointer and DRP offsets from the start of TLS data area. // https://www.linux-mips.org/wiki/NPTL - if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 || - Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64 || - Type == R_MICROMIPS_TLS_DTPREL_HI16 || - Type == R_MICROMIPS_TLS_DTPREL_LO16) { - Val -= 0x8000; - } else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 || - Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64 || - Type == R_MICROMIPS_TLS_TPREL_HI16 || - Type == R_MICROMIPS_TLS_TPREL_LO16) { - Val -= 0x7000; + if (type == R_MIPS_TLS_DTPREL_HI16 || type == R_MIPS_TLS_DTPREL_LO16 || + type == R_MIPS_TLS_DTPREL32 || type == R_MIPS_TLS_DTPREL64 || + type == R_MICROMIPS_TLS_DTPREL_HI16 || + type == R_MICROMIPS_TLS_DTPREL_LO16) { + val -= 0x8000; + } else if (type == R_MIPS_TLS_TPREL_HI16 || type == R_MIPS_TLS_TPREL_LO16 || + type == R_MIPS_TLS_TPREL32 || type == R_MIPS_TLS_TPREL64 || + type == R_MICROMIPS_TLS_TPREL_HI16 || + type == R_MICROMIPS_TLS_TPREL_LO16) { + val -= 0x7000; } - switch (Type) { + switch (type) { case R_MIPS_32: case R_MIPS_GPREL32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL32: - write32(Loc, Val); + write32(loc, val); break; case R_MIPS_64: case R_MIPS_TLS_DTPREL64: case R_MIPS_TLS_TPREL64: - write64(Loc, Val); + write64(loc, val); break; case R_MIPS_26: - writeValue(Loc, Val, 26, 2); + writeValue(loc, val, 26, 2); break; case R_MIPS_GOT16: // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode // is updated addend (not a GOT index). In that case write high 16 bits // to store a correct addend value. - if (Config->Relocatable) { - writeValue(Loc, Val + 0x8000, 16, 16); + if (config->relocatable) { + writeValue(loc, val + 0x8000, 16, 16); } else { - checkInt(Loc, Val, 16, Type); - writeValue(Loc, Val, 16, 0); + checkInt(loc, val, 16, type); + writeValue(loc, val, 16, 0); } break; case R_MICROMIPS_GOT16: - if (Config->Relocatable) { - writeShuffleValue(Loc, Val + 0x8000, 16, 16); + if (config->relocatable) { + writeShuffleValue(loc, val + 0x8000, 16, 16); } else { - checkInt(Loc, Val, 16, Type); - writeShuffleValue(Loc, Val, 16, 0); + checkInt(loc, val, 16, type); + writeShuffleValue(loc, val, 16, 0); } break; case R_MIPS_CALL16: @@ -586,7 +586,7 @@ case R_MIPS_TLS_GD: case R_MIPS_TLS_GOTTPREL: case R_MIPS_TLS_LDM: - checkInt(Loc, Val, 16, Type); + checkInt(loc, val, 16, type); LLVM_FALLTHROUGH; case R_MIPS_CALL_LO16: case R_MIPS_GOT_LO16: @@ -595,13 +595,13 @@ case R_MIPS_PCLO16: case R_MIPS_TLS_DTPREL_LO16: case R_MIPS_TLS_TPREL_LO16: - writeValue(Loc, Val, 16, 0); + writeValue(loc, val, 16, 0); break; case R_MICROMIPS_GPREL16: case R_MICROMIPS_TLS_GD: case R_MICROMIPS_TLS_LDM: - checkInt(Loc, Val, 16, Type); - writeShuffleValue(Loc, Val, 16, 0); + checkInt(loc, val, 16, type); + writeShuffleValue(loc, val, 16, 0); break; case R_MICROMIPS_CALL16: case R_MICROMIPS_CALL_LO16: @@ -609,11 +609,11 @@ case R_MICROMIPS_TLS_DTPREL_LO16: case R_MICROMIPS_TLS_GOTTPREL: case R_MICROMIPS_TLS_TPREL_LO16: - writeShuffleValue(Loc, Val, 16, 0); + writeShuffleValue(loc, val, 16, 0); break; case R_MICROMIPS_GPREL7_S2: - checkInt(Loc, Val, 7, Type); - writeShuffleValue(Loc, Val, 7, 2); + checkInt(loc, val, 7, type); + writeShuffleValue(loc, val, 7, 2); break; case R_MIPS_CALL_HI16: case R_MIPS_GOT_HI16: @@ -621,113 +621,113 @@ case R_MIPS_PCHI16: case R_MIPS_TLS_DTPREL_HI16: case R_MIPS_TLS_TPREL_HI16: - writeValue(Loc, Val + 0x8000, 16, 16); + writeValue(loc, val + 0x8000, 16, 16); break; case R_MICROMIPS_CALL_HI16: case R_MICROMIPS_GOT_HI16: case R_MICROMIPS_HI16: case R_MICROMIPS_TLS_DTPREL_HI16: case R_MICROMIPS_TLS_TPREL_HI16: - writeShuffleValue(Loc, Val + 0x8000, 16, 16); + writeShuffleValue(loc, val + 0x8000, 16, 16); break; case R_MIPS_HIGHER: - writeValue(Loc, Val + 0x80008000, 16, 32); + writeValue(loc, val + 0x80008000, 16, 32); break; case R_MIPS_HIGHEST: - writeValue(Loc, Val + 0x800080008000, 16, 48); + writeValue(loc, val + 0x800080008000, 16, 48); break; case R_MIPS_JALR: case R_MICROMIPS_JALR: // Ignore this optimization relocation for now break; case R_MIPS_PC16: - checkAlignment(Loc, Val, 4, Type); - checkInt(Loc, Val, 18, Type); - writeValue(Loc, Val, 16, 2); + checkAlignment(loc, val, 4, type); + checkInt(loc, val, 18, type); + writeValue(loc, val, 16, 2); break; case R_MIPS_PC19_S2: - checkAlignment(Loc, Val, 4, Type); - checkInt(Loc, Val, 21, Type); - writeValue(Loc, Val, 19, 2); + checkAlignment(loc, val, 4, type); + checkInt(loc, val, 21, type); + writeValue(loc, val, 19, 2); break; case R_MIPS_PC21_S2: - checkAlignment(Loc, Val, 4, Type); - checkInt(Loc, Val, 23, Type); - writeValue(Loc, Val, 21, 2); + checkAlignment(loc, val, 4, type); + checkInt(loc, val, 23, type); + writeValue(loc, val, 21, 2); break; case R_MIPS_PC26_S2: - checkAlignment(Loc, Val, 4, Type); - checkInt(Loc, Val, 28, Type); - writeValue(Loc, Val, 26, 2); + checkAlignment(loc, val, 4, type); + checkInt(loc, val, 28, type); + writeValue(loc, val, 26, 2); break; case R_MIPS_PC32: - writeValue(Loc, Val, 32, 0); + writeValue(loc, val, 32, 0); break; case R_MICROMIPS_26_S1: case R_MICROMIPS_PC26_S1: - checkInt(Loc, Val, 27, Type); - writeShuffleValue(Loc, Val, 26, 1); + checkInt(loc, val, 27, type); + writeShuffleValue(loc, val, 26, 1); break; case R_MICROMIPS_PC7_S1: - checkInt(Loc, Val, 8, Type); - writeMicroRelocation16(Loc, Val, 7, 1); + checkInt(loc, val, 8, type); + writeMicroRelocation16(loc, val, 7, 1); break; case R_MICROMIPS_PC10_S1: - checkInt(Loc, Val, 11, Type); - writeMicroRelocation16(Loc, Val, 10, 1); + checkInt(loc, val, 11, type); + writeMicroRelocation16(loc, val, 10, 1); break; case R_MICROMIPS_PC16_S1: - checkInt(Loc, Val, 17, Type); - writeShuffleValue(Loc, Val, 16, 1); + checkInt(loc, val, 17, type); + writeShuffleValue(loc, val, 16, 1); break; case R_MICROMIPS_PC18_S3: - checkInt(Loc, Val, 21, Type); - writeShuffleValue(Loc, Val, 18, 3); + checkInt(loc, val, 21, type); + writeShuffleValue(loc, val, 18, 3); break; case R_MICROMIPS_PC19_S2: - checkInt(Loc, Val, 21, Type); - writeShuffleValue(Loc, Val, 19, 2); + checkInt(loc, val, 21, type); + writeShuffleValue(loc, val, 19, 2); break; case R_MICROMIPS_PC21_S1: - checkInt(Loc, Val, 22, Type); - writeShuffleValue(Loc, Val, 21, 1); + checkInt(loc, val, 22, type); + writeShuffleValue(loc, val, 21, 1); break; case R_MICROMIPS_PC23_S2: - checkInt(Loc, Val, 25, Type); - writeShuffleValue(Loc, Val, 23, 2); + checkInt(loc, val, 25, type); + writeShuffleValue(loc, val, 23, 2); break; default: llvm_unreachable("unknown relocation"); } } -template bool MIPS::usesOnlyLowPageBits(RelType Type) const { - return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST || - Type == R_MICROMIPS_LO16; +template bool MIPS::usesOnlyLowPageBits(RelType type) const { + return type == R_MIPS_LO16 || type == R_MIPS_GOT_OFST || + type == R_MICROMIPS_LO16; } // Return true if the symbol is a PIC function. -template bool elf::isMipsPIC(const Defined *Sym) { - if (!Sym->isFunc()) +template bool elf::isMipsPIC(const Defined *sym) { + if (!sym->isFunc()) return false; - if (Sym->StOther & STO_MIPS_PIC) + if (sym->stOther & STO_MIPS_PIC) return true; - if (!Sym->Section) + if (!sym->section) return false; - ObjFile *File = - cast(Sym->Section)->template getFile(); - if (!File) + ObjFile *file = + cast(sym->section)->template getFile(); + if (!file) return false; - return File->getObj().getHeader()->e_flags & EF_MIPS_PIC; + return file->getObj().getHeader()->e_flags & EF_MIPS_PIC; } template TargetInfo *elf::getMipsTargetInfo() { - static MIPS Target; - return &Target; + static MIPS target; + return ⌖ } template TargetInfo *elf::getMipsTargetInfo(); Index: lld/trunk/ELF/Arch/MipsArchTree.cpp =================================================================== --- lld/trunk/ELF/Arch/MipsArchTree.cpp +++ lld/trunk/ELF/Arch/MipsArchTree.cpp @@ -28,18 +28,18 @@ namespace { struct ArchTreeEdge { - uint32_t Child; - uint32_t Parent; + uint32_t child; + uint32_t parent; }; struct FileFlags { - InputFile *File; - uint32_t Flags; + InputFile *file; + uint32_t flags; }; } // namespace -static StringRef getAbiName(uint32_t Flags) { - switch (Flags) { +static StringRef getAbiName(uint32_t flags) { + switch (flags) { case 0: return "n64"; case EF_MIPS_ABI2: @@ -57,76 +57,76 @@ } } -static StringRef getNanName(bool IsNan2008) { - return IsNan2008 ? "2008" : "legacy"; +static StringRef getNanName(bool isNan2008) { + return isNan2008 ? "2008" : "legacy"; } -static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; } +static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; } -static void checkFlags(ArrayRef Files) { - assert(!Files.empty() && "expected non-empty file list"); +static void checkFlags(ArrayRef files) { + assert(!files.empty() && "expected non-empty file list"); - uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2); - bool Nan = Files[0].Flags & EF_MIPS_NAN2008; - bool Fp = Files[0].Flags & EF_MIPS_FP64; + uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2); + bool nan = files[0].flags & EF_MIPS_NAN2008; + bool fp = files[0].flags & EF_MIPS_FP64; - for (const FileFlags &F : Files) { - if (Config->Is64 && F.Flags & EF_MIPS_MICROMIPS) - error(toString(F.File) + ": microMIPS 64-bit is not supported"); + for (const FileFlags &f : files) { + if (config->is64 && f.flags & EF_MIPS_MICROMIPS) + error(toString(f.file) + ": microMIPS 64-bit is not supported"); - uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2); - if (ABI != ABI2) - error(toString(F.File) + ": ABI '" + getAbiName(ABI2) + - "' is incompatible with target ABI '" + getAbiName(ABI) + "'"); + uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2); + if (abi != abi2) + error(toString(f.file) + ": ABI '" + getAbiName(abi2) + + "' is incompatible with target ABI '" + getAbiName(abi) + "'"); - bool Nan2 = F.Flags & EF_MIPS_NAN2008; - if (Nan != Nan2) - error(toString(F.File) + ": -mnan=" + getNanName(Nan2) + - " is incompatible with target -mnan=" + getNanName(Nan)); + bool nan2 = f.flags & EF_MIPS_NAN2008; + if (nan != nan2) + error(toString(f.file) + ": -mnan=" + getNanName(nan2) + + " is incompatible with target -mnan=" + getNanName(nan)); - bool Fp2 = F.Flags & EF_MIPS_FP64; - if (Fp != Fp2) - error(toString(F.File) + ": -mfp" + getFpName(Fp2) + - " is incompatible with target -mfp" + getFpName(Fp)); + bool fp2 = f.flags & EF_MIPS_FP64; + if (fp != fp2) + error(toString(f.file) + ": -mfp" + getFpName(fp2) + + " is incompatible with target -mfp" + getFpName(fp)); } } -static uint32_t getMiscFlags(ArrayRef Files) { - uint32_t Ret = 0; - for (const FileFlags &F : Files) - Ret |= F.Flags & +static uint32_t getMiscFlags(ArrayRef files) { + uint32_t ret = 0; + for (const FileFlags &f : files) + ret |= f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER | EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE); - return Ret; + return ret; } -static uint32_t getPicFlags(ArrayRef Files) { +static uint32_t getPicFlags(ArrayRef files) { // Check PIC/non-PIC compatibility. - bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); - for (const FileFlags &F : Files.slice(1)) { - bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); - if (IsPic && !IsPic2) - warn(toString(F.File) + + bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); + for (const FileFlags &f : files.slice(1)) { + bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); + if (isPic && !isPic2) + warn(toString(f.file) + ": linking non-abicalls code with abicalls code " + - toString(Files[0].File)); - if (!IsPic && IsPic2) - warn(toString(F.File) + + toString(files[0].file)); + if (!isPic && isPic2) + warn(toString(f.file) + ": linking abicalls code with non-abicalls code " + - toString(Files[0].File)); + toString(files[0].file)); } // Compute the result PIC/non-PIC flag. - uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); - for (const FileFlags &F : Files.slice(1)) - Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC); + uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); + for (const FileFlags &f : files.slice(1)) + ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); // PIC code is inherently CPIC and may not set CPIC flag explicitly. - if (Ret & EF_MIPS_PIC) - Ret |= EF_MIPS_CPIC; - return Ret; + if (ret & EF_MIPS_PIC) + ret |= EF_MIPS_CPIC; + return ret; } -static ArchTreeEdge ArchTree[] = { +static ArchTreeEdge archTree[] = { // MIPS32R6 and MIPS64R6 are not compatible with other extensions // MIPS64R2 extensions. {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2}, @@ -166,25 +166,25 @@ {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1}, }; -static bool isArchMatched(uint32_t New, uint32_t Res) { - if (New == Res) +static bool isArchMatched(uint32_t New, uint32_t res) { + if (New == res) return true; - if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res)) + if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res)) return true; - if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res)) + if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res)) return true; - for (const auto &Edge : ArchTree) { - if (Res == Edge.Child) { - Res = Edge.Parent; - if (Res == New) + for (const auto &edge : archTree) { + if (res == edge.child) { + res = edge.parent; + if (res == New) return true; } } return false; } -static StringRef getMachName(uint32_t Flags) { - switch (Flags & EF_MIPS_MACH) { +static StringRef getMachName(uint32_t flags) { + switch (flags & EF_MIPS_MACH) { case EF_MIPS_MACH_NONE: return ""; case EF_MIPS_MACH_3900: @@ -228,8 +228,8 @@ } } -static StringRef getArchName(uint32_t Flags) { - switch (Flags & EF_MIPS_ARCH) { +static StringRef getArchName(uint32_t flags) { + switch (flags & EF_MIPS_ARCH) { case EF_MIPS_ARCH_1: return "mips1"; case EF_MIPS_ARCH_2: @@ -257,12 +257,12 @@ } } -static std::string getFullArchName(uint32_t Flags) { - StringRef Arch = getArchName(Flags); - StringRef Mach = getMachName(Flags); - if (Mach.empty()) - return Arch.str(); - return (Arch + " (" + Mach + ")").str(); +static std::string getFullArchName(uint32_t flags) { + StringRef arch = getArchName(flags); + StringRef mach = getMachName(flags); + if (mach.empty()) + return arch.str(); + return (arch + " (" + mach + ")").str(); } // There are (arguably too) many MIPS ISAs out there. Their relationships @@ -274,55 +274,55 @@ // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32 // are incompatible because nor mips3 is a parent for misp32, nor mips32 // is a parent for mips3. -static uint32_t getArchFlags(ArrayRef Files) { - uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH); +static uint32_t getArchFlags(ArrayRef files) { + uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH); - for (const FileFlags &F : Files.slice(1)) { - uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH); + for (const FileFlags &f : files.slice(1)) { + uint32_t New = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH); // Check ISA compatibility. - if (isArchMatched(New, Ret)) + if (isArchMatched(New, ret)) continue; - if (!isArchMatched(Ret, New)) { - error("incompatible target ISA:\n>>> " + toString(Files[0].File) + ": " + - getFullArchName(Ret) + "\n>>> " + toString(F.File) + ": " + + if (!isArchMatched(ret, New)) { + error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " + + getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " + getFullArchName(New)); return 0; } - Ret = New; + ret = New; } - return Ret; + return ret; } template uint32_t elf::calcMipsEFlags() { - std::vector V; - for (InputFile *F : ObjectFiles) - V.push_back({F, cast>(F)->getObj().getHeader()->e_flags}); - if (V.empty()) + std::vector v; + for (InputFile *f : objectFiles) + v.push_back({f, cast>(f)->getObj().getHeader()->e_flags}); + if (v.empty()) return 0; - checkFlags(V); - return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V); + checkFlags(v); + return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v); } -static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) { - if (FpA == FpB) +static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) { + if (fpA == fpB) return 0; - if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY) + if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY) return 1; - if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A && - FpA == Mips::Val_GNU_MIPS_ABI_FP_64) + if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A && + fpA == Mips::Val_GNU_MIPS_ABI_FP_64) return 1; - if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX) + if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX) return -1; - if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || - FpA == Mips::Val_GNU_MIPS_ABI_FP_64 || - FpA == Mips::Val_GNU_MIPS_ABI_FP_64A) + if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || + fpA == Mips::Val_GNU_MIPS_ABI_FP_64 || + fpA == Mips::Val_GNU_MIPS_ABI_FP_64A) return 1; return -1; } -static StringRef getMipsFpAbiName(uint8_t FpAbi) { - switch (FpAbi) { +static StringRef getMipsFpAbiName(uint8_t fpAbi) { + switch (fpAbi) { case Mips::Val_GNU_MIPS_ABI_FP_ANY: return "any"; case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE: @@ -344,43 +344,43 @@ } } -uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, - StringRef FileName) { - if (compareMipsFpAbi(NewFlag, OldFlag) >= 0) - return NewFlag; - if (compareMipsFpAbi(OldFlag, NewFlag) < 0) - error(FileName + ": floating point ABI '" + getMipsFpAbiName(NewFlag) + +uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag, + StringRef fileName) { + if (compareMipsFpAbi(newFlag, oldFlag) >= 0) + return newFlag; + if (compareMipsFpAbi(oldFlag, newFlag) < 0) + error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) + "' is incompatible with target floating point ABI '" + - getMipsFpAbiName(OldFlag) + "'"); - return OldFlag; + getMipsFpAbiName(oldFlag) + "'"); + return oldFlag; } -template static bool isN32Abi(const InputFile *F) { - if (auto *EF = dyn_cast(F)) - return EF->template getObj().getHeader()->e_flags & EF_MIPS_ABI2; +template static bool isN32Abi(const InputFile *f) { + if (auto *ef = dyn_cast(f)) + return ef->template getObj().getHeader()->e_flags & EF_MIPS_ABI2; return false; } -bool elf::isMipsN32Abi(const InputFile *F) { - switch (Config->EKind) { +bool elf::isMipsN32Abi(const InputFile *f) { + switch (config->ekind) { case ELF32LEKind: - return isN32Abi(F); + return isN32Abi(f); case ELF32BEKind: - return isN32Abi(F); + return isN32Abi(f); case ELF64LEKind: - return isN32Abi(F); + return isN32Abi(f); case ELF64BEKind: - return isN32Abi(F); + return isN32Abi(f); default: llvm_unreachable("unknown Config->EKind"); } } -bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; } +bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; } bool elf::isMipsR6() { - uint32_t Arch = Config->EFlags & EF_MIPS_ARCH; - return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; + uint32_t arch = config->eflags & EF_MIPS_ARCH; + return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6; } template uint32_t elf::calcMipsEFlags(); Index: lld/trunk/ELF/Arch/PPC.cpp =================================================================== --- lld/trunk/ELF/Arch/PPC.cpp +++ lld/trunk/ELF/Arch/PPC.cpp @@ -23,45 +23,45 @@ class PPC final : public TargetInfo { public: PPC(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; - void writeGotHeader(uint8_t *Buf) const override; - void writePltHeader(uint8_t *Buf) const override { + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + void writeGotHeader(uint8_t *buf) const override; + void writePltHeader(uint8_t *buf) const override { llvm_unreachable("should call writePPC32GlinkSection() instead"); } - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override { + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override { llvm_unreachable("should call writePPC32GlinkSection() instead"); } - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - bool needsThunk(RelExpr Expr, RelType RelocType, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + bool needsThunk(RelExpr expr, RelType relocType, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const override; uint32_t getThunkSectionSpacing() const override; - bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - int getTlsGdRelaxSkip(RelType Type) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + int getTlsGdRelaxSkip(RelType type) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace -static uint16_t lo(uint32_t V) { return V; } -static uint16_t ha(uint32_t V) { return (V + 0x8000) >> 16; } +static uint16_t lo(uint32_t v) { return v; } +static uint16_t ha(uint32_t v) { return (v + 0x8000) >> 16; } -static uint32_t readFromHalf16(const uint8_t *Loc) { - return read32(Config->IsLE ? Loc : Loc - 2); +static uint32_t readFromHalf16(const uint8_t *loc) { + return read32(config->isLE ? loc : loc - 2); } -static void writeFromHalf16(uint8_t *Loc, uint32_t Insn) { - write32(Config->IsLE ? Loc : Loc - 2, Insn); +static void writeFromHalf16(uint8_t *loc, uint32_t insn) { + write32(config->isLE ? loc : loc - 2, insn); } -void elf::writePPC32GlinkSection(uint8_t *Buf, size_t NumEntries) { +void elf::writePPC32GlinkSection(uint8_t *buf, size_t numEntries) { // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an // absolute address from a specific .plt slot (usually called .got.plt on // other targets) and jumps there. @@ -72,124 +72,124 @@ // instruction in .glink, filled in by PPC::writeGotPlt(). // Write N `b PLTresolve` first. - for (size_t I = 0; I != NumEntries; ++I) - write32(Buf + 4 * I, 0x48000000 | 4 * (NumEntries - I)); - Buf += 4 * NumEntries; + for (size_t i = 0; i != numEntries; ++i) + write32(buf + 4 * i, 0x48000000 | 4 * (numEntries - i)); + buf += 4 * numEntries; // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve() // computes the PLT index (by computing the distance from the landing b to // itself) and calls _dl_runtime_resolve() (in glibc). - uint32_t GOT = In.Got->getVA(); - uint32_t Glink = In.Plt->getVA(); // VA of .glink - const uint8_t *End = Buf + 64; - if (Config->Pic) { - uint32_t AfterBcl = In.Plt->getSize() - Target->PltHeaderSize + 12; - uint32_t GotBcl = GOT + 4 - (Glink + AfterBcl); - write32(Buf + 0, 0x3d6b0000 | ha(AfterBcl)); // addis r11,r11,1f-glink@ha - write32(Buf + 4, 0x7c0802a6); // mflr r0 - write32(Buf + 8, 0x429f0005); // bcl 20,30,.+4 - write32(Buf + 12, 0x396b0000 | lo(AfterBcl)); // 1: addi r11,r11,1b-.glink@l - write32(Buf + 16, 0x7d8802a6); // mflr r12 - write32(Buf + 20, 0x7c0803a6); // mtlr r0 - write32(Buf + 24, 0x7d6c5850); // sub r11,r11,r12 - write32(Buf + 28, 0x3d8c0000 | ha(GotBcl)); // addis 12,12,GOT+4-1b@ha - if (ha(GotBcl) == ha(GotBcl + 4)) { - write32(Buf + 32, 0x800c0000 | lo(GotBcl)); // lwz r0,r12,GOT+4-1b@l(r12) - write32(Buf + 36, - 0x818c0000 | lo(GotBcl + 4)); // lwz r12,r12,GOT+8-1b@l(r12) + uint32_t got = in.got->getVA(); + uint32_t glink = in.plt->getVA(); // VA of .glink + const uint8_t *end = buf + 64; + if (config->isPic) { + uint32_t afterBcl = in.plt->getSize() - target->pltHeaderSize + 12; + uint32_t gotBcl = got + 4 - (glink + afterBcl); + write32(buf + 0, 0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink@ha + write32(buf + 4, 0x7c0802a6); // mflr r0 + write32(buf + 8, 0x429f0005); // bcl 20,30,.+4 + write32(buf + 12, 0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-.glink@l + write32(buf + 16, 0x7d8802a6); // mflr r12 + write32(buf + 20, 0x7c0803a6); // mtlr r0 + write32(buf + 24, 0x7d6c5850); // sub r11,r11,r12 + write32(buf + 28, 0x3d8c0000 | ha(gotBcl)); // addis 12,12,GOT+4-1b@ha + if (ha(gotBcl) == ha(gotBcl + 4)) { + write32(buf + 32, 0x800c0000 | lo(gotBcl)); // lwz r0,r12,GOT+4-1b@l(r12) + write32(buf + 36, + 0x818c0000 | lo(gotBcl + 4)); // lwz r12,r12,GOT+8-1b@l(r12) } else { - write32(Buf + 32, 0x840c0000 | lo(GotBcl)); // lwzu r0,r12,GOT+4-1b@l(r12) - write32(Buf + 36, 0x818c0000 | 4); // lwz r12,r12,4(r12) + write32(buf + 32, 0x840c0000 | lo(gotBcl)); // lwzu r0,r12,GOT+4-1b@l(r12) + write32(buf + 36, 0x818c0000 | 4); // lwz r12,r12,4(r12) } - write32(Buf + 40, 0x7c0903a6); // mtctr 0 - write32(Buf + 44, 0x7c0b5a14); // add r0,11,11 - write32(Buf + 48, 0x7d605a14); // add r11,0,11 - write32(Buf + 52, 0x4e800420); // bctr - Buf += 56; + write32(buf + 40, 0x7c0903a6); // mtctr 0 + write32(buf + 44, 0x7c0b5a14); // add r0,11,11 + write32(buf + 48, 0x7d605a14); // add r11,0,11 + write32(buf + 52, 0x4e800420); // bctr + buf += 56; } else { - write32(Buf + 0, 0x3d800000 | ha(GOT + 4)); // lis r12,GOT+4@ha - write32(Buf + 4, 0x3d6b0000 | ha(-Glink)); // addis r11,r11,-Glink@ha - if (ha(GOT + 4) == ha(GOT + 8)) - write32(Buf + 8, 0x800c0000 | lo(GOT + 4)); // lwz r0,GOT+4@l(r12) + write32(buf + 0, 0x3d800000 | ha(got + 4)); // lis r12,GOT+4@ha + write32(buf + 4, 0x3d6b0000 | ha(-glink)); // addis r11,r11,-Glink@ha + if (ha(got + 4) == ha(got + 8)) + write32(buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4@l(r12) else - write32(Buf + 8, 0x840c0000 | lo(GOT + 4)); // lwzu r0,GOT+4@l(r12) - write32(Buf + 12, 0x396b0000 | lo(-Glink)); // addi r11,r11,-Glink@l - write32(Buf + 16, 0x7c0903a6); // mtctr r0 - write32(Buf + 20, 0x7c0b5a14); // add r0,r11,r11 - if (ha(GOT + 4) == ha(GOT + 8)) - write32(Buf + 24, 0x818c0000 | lo(GOT + 8)); // lwz r12,GOT+8@ha(r12) + write32(buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4@l(r12) + write32(buf + 12, 0x396b0000 | lo(-glink)); // addi r11,r11,-Glink@l + write32(buf + 16, 0x7c0903a6); // mtctr r0 + write32(buf + 20, 0x7c0b5a14); // add r0,r11,r11 + if (ha(got + 4) == ha(got + 8)) + write32(buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8@ha(r12) else - write32(Buf + 24, 0x818c0000 | 4); // lwz r12,4(r12) - write32(Buf + 28, 0x7d605a14); // add r11,r0,r11 - write32(Buf + 32, 0x4e800420); // bctr - Buf += 36; + write32(buf + 24, 0x818c0000 | 4); // lwz r12,4(r12) + write32(buf + 28, 0x7d605a14); // add r11,r0,r11 + write32(buf + 32, 0x4e800420); // bctr + buf += 36; } // Pad with nop. They should not be executed. - for (; Buf < End; Buf += 4) - write32(Buf, 0x60000000); + for (; buf < end; buf += 4) + write32(buf, 0x60000000); } PPC::PPC() { - GotRel = R_PPC_GLOB_DAT; - NoneRel = R_PPC_NONE; - PltRel = R_PPC_JMP_SLOT; - RelativeRel = R_PPC_RELATIVE; - IRelativeRel = R_PPC_IRELATIVE; - SymbolicRel = R_PPC_ADDR32; - GotBaseSymInGotPlt = false; - GotHeaderEntriesNum = 3; - GotPltHeaderEntriesNum = 0; - PltHeaderSize = 64; // size of PLTresolve in .glink - PltEntrySize = 4; - - NeedsThunks = true; - - TlsModuleIndexRel = R_PPC_DTPMOD32; - TlsOffsetRel = R_PPC_DTPREL32; - TlsGotRel = R_PPC_TPREL32; + gotRel = R_PPC_GLOB_DAT; + noneRel = R_PPC_NONE; + pltRel = R_PPC_JMP_SLOT; + relativeRel = R_PPC_RELATIVE; + iRelativeRel = R_PPC_IRELATIVE; + symbolicRel = R_PPC_ADDR32; + gotBaseSymInGotPlt = false; + gotHeaderEntriesNum = 3; + gotPltHeaderEntriesNum = 0; + pltHeaderSize = 64; // size of PLTresolve in .glink + pltEntrySize = 4; + + needsThunks = true; + + tlsModuleIndexRel = R_PPC_DTPMOD32; + tlsOffsetRel = R_PPC_DTPREL32; + tlsGotRel = R_PPC_TPREL32; - DefaultMaxPageSize = 65536; - DefaultImageBase = 0x10000000; + defaultMaxPageSize = 65536; + defaultImageBase = 0x10000000; - write32(TrapInstr.data(), 0x7fe00008); + write32(trapInstr.data(), 0x7fe00008); } -void PPC::writeGotHeader(uint8_t *Buf) const { +void PPC::writeGotHeader(uint8_t *buf) const { // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1], // link_map in _GLOBAL_OFFSET_TABLE_[2]. - write32(Buf, Main->Dynamic->getVA()); + write32(buf, mainPart->dynamic->getVA()); } -void PPC::writeGotPlt(uint8_t *Buf, const Symbol &S) const { +void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const { // Address of the symbol resolver stub in .glink . - write32(Buf, In.Plt->getVA() + 4 * S.PltIndex); + write32(buf, in.plt->getVA() + 4 * s.pltIndex); } -bool PPC::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { - if (Type != R_PPC_REL24 && Type != R_PPC_PLTREL24) +bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { + if (type != R_PPC_REL24 && type != R_PPC_PLTREL24) return false; - if (S.isInPlt()) + if (s.isInPlt()) return true; - if (S.isUndefWeak()) + if (s.isUndefWeak()) return false; - return !(Expr == R_PC && PPC::inBranchRange(Type, BranchAddr, S.getVA())); + return !(expr == R_PC && PPC::inBranchRange(type, branchAddr, s.getVA())); } uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; } -bool PPC::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { - uint64_t Offset = Dst - Src; - if (Type == R_PPC_REL24 || Type == R_PPC_PLTREL24) - return isInt<26>(Offset); +bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + uint64_t offset = dst - src; + if (type == R_PPC_REL24 || type == R_PPC_PLTREL24) + return isInt<26>(offset); llvm_unreachable("unsupported relocation type used in branch"); } -RelExpr PPC::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr PPC::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_PPC_DTPREL16: case R_PPC_DTPREL16_HA: case R_PPC_DTPREL16_HI: @@ -231,45 +231,45 @@ } } -RelType PPC::getDynRel(RelType Type) const { - if (Type == R_PPC_ADDR32) - return Type; +RelType PPC::getDynRel(RelType type) const { + if (type == R_PPC_ADDR32) + return type; return R_PPC_NONE; } -static std::pair fromDTPREL(RelType Type, uint64_t Val) { - uint64_t DTPBiasedVal = Val - 0x8000; - switch (Type) { +static std::pair fromDTPREL(RelType type, uint64_t val) { + uint64_t dtpBiasedVal = val - 0x8000; + switch (type) { case R_PPC_DTPREL16: - return {R_PPC64_ADDR16, DTPBiasedVal}; + return {R_PPC64_ADDR16, dtpBiasedVal}; case R_PPC_DTPREL16_HA: - return {R_PPC_ADDR16_HA, DTPBiasedVal}; + return {R_PPC_ADDR16_HA, dtpBiasedVal}; case R_PPC_DTPREL16_HI: - return {R_PPC_ADDR16_HI, DTPBiasedVal}; + return {R_PPC_ADDR16_HI, dtpBiasedVal}; case R_PPC_DTPREL16_LO: - return {R_PPC_ADDR16_LO, DTPBiasedVal}; + return {R_PPC_ADDR16_LO, dtpBiasedVal}; case R_PPC_DTPREL32: - return {R_PPC_ADDR32, DTPBiasedVal}; + return {R_PPC_ADDR32, dtpBiasedVal}; default: - return {Type, Val}; + return {type, val}; } } -void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - RelType NewType; - std::tie(NewType, Val) = fromDTPREL(Type, Val); - switch (NewType) { +void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + RelType newType; + std::tie(newType, val) = fromDTPREL(type, val); + switch (newType) { case R_PPC_ADDR16: - checkIntUInt(Loc, Val, 16, Type); - write16(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16(loc, val); break; case R_PPC_GOT16: case R_PPC_GOT_TLSGD16: case R_PPC_GOT_TLSLD16: case R_PPC_GOT_TPREL16: case R_PPC_TPREL16: - checkInt(Loc, Val, 16, Type); - write16(Loc, Val); + checkInt(loc, val, 16, type); + write16(loc, val); break; case R_PPC_ADDR16_HA: case R_PPC_DTPREL16_HA: @@ -278,7 +278,7 @@ case R_PPC_GOT_TPREL16_HA: case R_PPC_REL16_HA: case R_PPC_TPREL16_HA: - write16(Loc, ha(Val)); + write16(loc, ha(val)); break; case R_PPC_ADDR16_HI: case R_PPC_DTPREL16_HI: @@ -287,7 +287,7 @@ case R_PPC_GOT_TPREL16_HI: case R_PPC_REL16_HI: case R_PPC_TPREL16_HI: - write16(Loc, Val >> 16); + write16(loc, val >> 16); break; case R_PPC_ADDR16_LO: case R_PPC_DTPREL16_LO: @@ -296,43 +296,43 @@ case R_PPC_GOT_TPREL16_LO: case R_PPC_REL16_LO: case R_PPC_TPREL16_LO: - write16(Loc, Val); + write16(loc, val); break; case R_PPC_ADDR32: case R_PPC_REL32: - write32(Loc, Val); + write32(loc, val); break; case R_PPC_REL14: { - uint32_t Mask = 0x0000FFFC; - checkInt(Loc, Val, 16, Type); - checkAlignment(Loc, Val, 4, Type); - write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); + uint32_t mask = 0x0000FFFC; + checkInt(loc, val, 16, type); + checkAlignment(loc, val, 4, type); + write32(loc, (read32(loc) & ~mask) | (val & mask)); break; } case R_PPC_REL24: case R_PPC_LOCAL24PC: case R_PPC_PLTREL24: { - uint32_t Mask = 0x03FFFFFC; - checkInt(Loc, Val, 26, Type); - checkAlignment(Loc, Val, 4, Type); - write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); + uint32_t mask = 0x03FFFFFC; + checkInt(loc, val, 26, type); + checkAlignment(loc, val, 4, type); + write32(loc, (read32(loc) & ~mask) | (val & mask)); break; } default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } -RelExpr PPC::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - if (Expr == R_RELAX_TLS_GD_TO_IE) +RelExpr PPC::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + if (expr == R_RELAX_TLS_GD_TO_IE) return R_RELAX_TLS_GD_TO_IE_GOT_OFF; - if (Expr == R_RELAX_TLS_LD_TO_LE) + if (expr == R_RELAX_TLS_LD_TO_LE) return R_RELAX_TLS_LD_TO_LE_ABS; - return Expr; + return expr; } -int PPC::getTlsGdRelaxSkip(RelType Type) const { +int PPC::getTlsGdRelaxSkip(RelType type) const { // A __tls_get_addr call instruction is marked with 2 relocations: // // R_PPC_TLSGD / R_PPC_TLSLD: marker relocation @@ -341,84 +341,84 @@ // After the relaxation we no longer call __tls_get_addr and should skip both // relocations to not create a false dependence on __tls_get_addr being // defined. - if (Type == R_PPC_TLSGD || Type == R_PPC_TLSLD) + if (type == R_PPC_TLSGD || type == R_PPC_TLSLD) return 2; return 1; } -void PPC::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC_GOT_TLSGD16: { // addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA) - uint32_t Insn = readFromHalf16(Loc); - writeFromHalf16(Loc, 0x80000000 | (Insn & 0x03ff0000)); - relocateOne(Loc, R_PPC_GOT_TPREL16, Val); + uint32_t insn = readFromHalf16(loc); + writeFromHalf16(loc, 0x80000000 | (insn & 0x03ff0000)); + relocateOne(loc, R_PPC_GOT_TPREL16, val); break; } case R_PPC_TLSGD: // bl __tls_get_addr(x@tldgd) --> add r3, r3, r2 - write32(Loc, 0x7c631214); + write32(loc, 0x7c631214); break; default: llvm_unreachable("unsupported relocation for TLS GD to IE relaxation"); } } -void PPC::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC_GOT_TLSGD16: // addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha - writeFromHalf16(Loc, 0x3c620000 | ha(Val)); + writeFromHalf16(loc, 0x3c620000 | ha(val)); break; case R_PPC_TLSGD: // bl __tls_get_addr(x@tldgd) --> add r3, r3, x@tprel@l - write32(Loc, 0x38630000 | lo(Val)); + write32(loc, 0x38630000 | lo(val)); break; default: llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); } } -void PPC::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC_GOT_TLSLD16: // addi r3, rA, x@got@tlsgd --> addis r3, r2, 0 - writeFromHalf16(Loc, 0x3c620000); + writeFromHalf16(loc, 0x3c620000); break; case R_PPC_TLSLD: // r3+x@dtprel computes r3+x-0x8000, while we want it to compute r3+x@tprel // = r3+x-0x7000, so add 4096 to r3. // bl __tls_get_addr(x@tlsld) --> addi r3, r3, 4096 - write32(Loc, 0x38631000); + write32(loc, 0x38631000); break; case R_PPC_DTPREL16: case R_PPC_DTPREL16_HA: case R_PPC_DTPREL16_HI: case R_PPC_DTPREL16_LO: - relocateOne(Loc, Type, Val); + relocateOne(loc, type, val); break; default: llvm_unreachable("unsupported relocation for TLS LD to LE relaxation"); } } -void PPC::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC_GOT_TPREL16: { // lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha - uint32_t RT = readFromHalf16(Loc) & 0x03e00000; - writeFromHalf16(Loc, 0x3c020000 | RT | ha(Val)); + uint32_t rt = readFromHalf16(loc) & 0x03e00000; + writeFromHalf16(loc, 0x3c020000 | rt | ha(val)); break; } case R_PPC_TLS: { - uint32_t Insn = read32(Loc); - if (Insn >> 26 != 31) + uint32_t insn = read32(loc); + if (insn >> 26 != 31) error("unrecognized instruction for IE to LE R_PPC_TLS"); // addi rT, rT, x@tls --> addi rT, rT, x@tprel@l - uint32_t DFormOp = getPPCDFormOp((read32(Loc) & 0x000007fe) >> 1); - if (DFormOp == 0) + uint32_t dFormOp = getPPCDFormOp((read32(loc) & 0x000007fe) >> 1); + if (dFormOp == 0) error("unrecognized instruction for IE to LE R_PPC_TLS"); - write32(Loc, (DFormOp << 26) | (Insn & 0x03ff0000) | lo(Val)); + write32(loc, (dFormOp << 26) | (insn & 0x03ff0000) | lo(val)); break; } default: @@ -427,6 +427,6 @@ } TargetInfo *elf::getPPCTargetInfo() { - static PPC Target; - return &Target; + static PPC target; + return ⌖ } Index: lld/trunk/ELF/Arch/PPC64.cpp =================================================================== --- lld/trunk/ELF/Arch/PPC64.cpp +++ lld/trunk/ELF/Arch/PPC64.cpp @@ -19,8 +19,8 @@ using namespace lld; using namespace lld::elf; -static uint64_t PPC64TocOffset = 0x8000; -static uint64_t DynamicThreadPointerOffset = 0x8000; +static uint64_t ppc64TocOffset = 0x8000; +static uint64_t dynamicThreadPointerOffset = 0x8000; // The instruction encoding of bits 21-30 from the ISA for the Xform and Dform // instructions that can be used as part of the initial exec TLS sequence. @@ -64,16 +64,16 @@ // TOC starts where the first of these sections starts. We always create a // .got when we see a relocation that uses it, so for us the start is always // the .got. - uint64_t TocVA = In.Got->getVA(); + uint64_t tocVA = in.got->getVA(); // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 // thus permitting a full 64 Kbytes segment. Note that the glibc startup // code (crt1.o) assumes that you can get from the TOC base to the // start of the .toc section with only a single (signed) 16-bit relocation. - return TocVA + PPC64TocOffset; + return tocVA + ppc64TocOffset; } -unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) { +unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) { // The offset is encoded into the 3 most significant bits of the st_other // field, with some special values described in section 3.4.1 of the ABI: // 0 --> Zero offset between the GEP and LEP, and the function does NOT use @@ -85,29 +85,29 @@ // 2 --> 2^2 = 4 bytes --> 1 instruction. // 6 --> 2^6 = 64 bytes --> 16 instructions. // 7 --> Reserved. - uint8_t GepToLep = (StOther >> 5) & 7; - if (GepToLep < 2) + uint8_t gepToLep = (stOther >> 5) & 7; + if (gepToLep < 2) return 0; // The value encoded in the st_other bits is the // log-base-2(offset). - if (GepToLep < 7) - return 1 << GepToLep; + if (gepToLep < 7) + return 1 << gepToLep; error("reserved value of 7 in the 3 most-significant-bits of st_other"); return 0; } -bool elf::isPPC64SmallCodeModelTocReloc(RelType Type) { +bool elf::isPPC64SmallCodeModelTocReloc(RelType type) { // The only small code model relocations that access the .toc section. - return Type == R_PPC64_TOC16 || Type == R_PPC64_TOC16_DS; + return type == R_PPC64_TOC16 || type == R_PPC64_TOC16_DS; } // Find the R_PPC64_ADDR64 in .rela.toc with matching offset. template static std::pair -getRelaTocSymAndAddend(InputSectionBase *TocSec, uint64_t Offset) { - if (TocSec->NumRelocations == 0) +getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) { + if (tocSec->numRelocations == 0) return {}; // .rela.toc contains exclusively R_PPC64_ADDR64 relocations sorted by @@ -119,16 +119,16 @@ // points to a relocation with larger r_offset. Do a linear probe then. // Constants are extremely uncommon in .toc and the extra number of array // accesses can be seen as a small constant. - ArrayRef Relas = TocSec->template relas(); - uint64_t Index = std::min(Offset / 8, Relas.size() - 1); + ArrayRef relas = tocSec->template relas(); + uint64_t index = std::min(offset / 8, relas.size() - 1); for (;;) { - if (Relas[Index].r_offset == Offset) { - Symbol &Sym = TocSec->getFile()->getRelocTargetSym(Relas[Index]); - return {dyn_cast(&Sym), getAddend(Relas[Index])}; + if (relas[index].r_offset == offset) { + Symbol &sym = tocSec->getFile()->getRelocTargetSym(relas[index]); + return {dyn_cast(&sym), getAddend(relas[index])}; } - if (Relas[Index].r_offset < Offset || Index == 0) + if (relas[index].r_offset < offset || index == 0) break; - --Index; + --index; } return {}; } @@ -153,35 +153,35 @@ // ld/lwa 3, 0(3) # load the value from the address // // Returns true if the relaxation is performed. -bool elf::tryRelaxPPC64TocIndirection(RelType Type, const Relocation &Rel, - uint8_t *BufLoc) { - assert(Config->TocOptimize); - if (Rel.Addend < 0) +bool elf::tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel, + uint8_t *bufLoc) { + assert(config->tocOptimize); + if (rel.addend < 0) return false; // If the symbol is not the .toc section, this isn't a toc-indirection. - Defined *DefSym = dyn_cast(Rel.Sym); - if (!DefSym || !DefSym->isSection() || DefSym->Section->Name != ".toc") + Defined *defSym = dyn_cast(rel.sym); + if (!defSym || !defSym->isSection() || defSym->section->name != ".toc") return false; - Defined *D; - int64_t Addend; - auto *TocISB = cast(DefSym->Section); - std::tie(D, Addend) = - Config->IsLE ? getRelaTocSymAndAddend(TocISB, Rel.Addend) - : getRelaTocSymAndAddend(TocISB, Rel.Addend); + Defined *d; + int64_t addend; + auto *tocISB = cast(defSym->section); + std::tie(d, addend) = + config->isLE ? getRelaTocSymAndAddend(tocISB, rel.addend) + : getRelaTocSymAndAddend(tocISB, rel.addend); // Only non-preemptable defined symbols can be relaxed. - if (!D || D->IsPreemptible) + if (!d || d->isPreemptible) return false; // Two instructions can materialize a 32-bit signed offset from the toc base. - uint64_t TocRelative = D->getVA(Addend) - getPPC64TocBase(); - if (!isInt<32>(TocRelative)) + uint64_t tocRelative = d->getVA(addend) - getPPC64TocBase(); + if (!isInt<32>(tocRelative)) return false; // Add PPC64TocOffset that will be subtracted by relocateOne(). - Target->relaxGot(BufLoc, Type, TocRelative + PPC64TocOffset); + target->relaxGot(bufLoc, type, tocRelative + ppc64TocOffset); return true; } @@ -189,30 +189,30 @@ class PPC64 final : public TargetInfo { public: PPC64(); - int getTlsGdRelaxSkip(RelType Type) const override; + int getTlsGdRelaxSkip(RelType type) const override; uint32_t calcEFlags() const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void writeGotHeader(uint8_t *Buf) const override; - bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + void writeGotHeader(uint8_t *buf) const override; + bool needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const override; uint32_t getThunkSectionSpacing() const override; - bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - void relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; + bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override; + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; - bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const override; + bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const override; }; } // namespace @@ -220,19 +220,19 @@ // #higher(value), #highera(value), #highest(value), and #highesta(value) // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi // document. -static uint16_t lo(uint64_t V) { return V; } -static uint16_t hi(uint64_t V) { return V >> 16; } -static uint16_t ha(uint64_t V) { return (V + 0x8000) >> 16; } -static uint16_t higher(uint64_t V) { return V >> 32; } -static uint16_t highera(uint64_t V) { return (V + 0x8000) >> 32; } -static uint16_t highest(uint64_t V) { return V >> 48; } -static uint16_t highesta(uint64_t V) { return (V + 0x8000) >> 48; } +static uint16_t lo(uint64_t v) { return v; } +static uint16_t hi(uint64_t v) { return v >> 16; } +static uint16_t ha(uint64_t v) { return (v + 0x8000) >> 16; } +static uint16_t higher(uint64_t v) { return v >> 32; } +static uint16_t highera(uint64_t v) { return (v + 0x8000) >> 32; } +static uint16_t highest(uint64_t v) { return v >> 48; } +static uint16_t highesta(uint64_t v) { return (v + 0x8000) >> 48; } // Extracts the 'PO' field of an instruction encoding. -static uint8_t getPrimaryOpCode(uint32_t Encoding) { return (Encoding >> 26); } +static uint8_t getPrimaryOpCode(uint32_t encoding) { return (encoding >> 26); } -static bool isDQFormInstruction(uint32_t Encoding) { - switch (getPrimaryOpCode(Encoding)) { +static bool isDQFormInstruction(uint32_t encoding) { + switch (getPrimaryOpCode(encoding)) { default: return false; case 56: @@ -242,12 +242,12 @@ // There are both DS and DQ instruction forms with this primary opcode. // Namely `lxv` and `stxv` are the DQ-forms that use it. // The DS 'XO' bits being set to 01 is restricted to DQ form. - return (Encoding & 3) == 0x1; + return (encoding & 3) == 0x1; } } -static bool isInstructionUpdateForm(uint32_t Encoding) { - switch (getPrimaryOpCode(Encoding)) { +static bool isInstructionUpdateForm(uint32_t encoding) { + switch (getPrimaryOpCode(encoding)) { default: return false; case LBZU: @@ -266,7 +266,7 @@ // between LD/LDU/LWA case LD: case STD: - return (Encoding & 3) == 1; + return (encoding & 3) == 1; } } @@ -275,38 +275,38 @@ // pointer is pointing into the middle of the word we want to extract, and on // little-endian it is pointing to the start of the word. These 2 helpers are to // simplify reading and writing in that context. -static void writeFromHalf16(uint8_t *Loc, uint32_t Insn) { - write32(Config->IsLE ? Loc : Loc - 2, Insn); +static void writeFromHalf16(uint8_t *loc, uint32_t insn) { + write32(config->isLE ? loc : loc - 2, insn); } -static uint32_t readFromHalf16(const uint8_t *Loc) { - return read32(Config->IsLE ? Loc : Loc - 2); +static uint32_t readFromHalf16(const uint8_t *loc) { + return read32(config->isLE ? loc : loc - 2); } PPC64::PPC64() { - GotRel = R_PPC64_GLOB_DAT; - NoneRel = R_PPC64_NONE; - PltRel = R_PPC64_JMP_SLOT; - RelativeRel = R_PPC64_RELATIVE; - IRelativeRel = R_PPC64_IRELATIVE; - SymbolicRel = R_PPC64_ADDR64; - PltEntrySize = 4; - GotBaseSymInGotPlt = false; - GotHeaderEntriesNum = 1; - GotPltHeaderEntriesNum = 2; - PltHeaderSize = 60; - NeedsThunks = true; + gotRel = R_PPC64_GLOB_DAT; + noneRel = R_PPC64_NONE; + pltRel = R_PPC64_JMP_SLOT; + relativeRel = R_PPC64_RELATIVE; + iRelativeRel = R_PPC64_IRELATIVE; + symbolicRel = R_PPC64_ADDR64; + pltEntrySize = 4; + gotBaseSymInGotPlt = false; + gotHeaderEntriesNum = 1; + gotPltHeaderEntriesNum = 2; + pltHeaderSize = 60; + needsThunks = true; - TlsModuleIndexRel = R_PPC64_DTPMOD64; - TlsOffsetRel = R_PPC64_DTPREL64; + tlsModuleIndexRel = R_PPC64_DTPMOD64; + tlsOffsetRel = R_PPC64_DTPREL64; - TlsGotRel = R_PPC64_TPREL64; + tlsGotRel = R_PPC64_TPREL64; - NeedsMoreStackNonSplit = false; + needsMoreStackNonSplit = false; // We need 64K pages (at least under glibc/Linux, the loader won't // set different permissions on a finer granularity than that). - DefaultMaxPageSize = 65536; + defaultMaxPageSize = 65536; // The PPC64 ELF ABI v1 spec, says: // @@ -316,12 +316,12 @@ // // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers // use 0x10000000 as the starting address. - DefaultImageBase = 0x10000000; + defaultImageBase = 0x10000000; - write32(TrapInstr.data(), 0x7fe00008); + write32(trapInstr.data(), 0x7fe00008); } -int PPC64::getTlsGdRelaxSkip(RelType Type) const { +int PPC64::getTlsGdRelaxSkip(RelType type) const { // A __tls_get_addr call instruction is marked with 2 relocations: // // R_PPC64_TLSGD / R_PPC64_TLSLD: marker relocation @@ -330,44 +330,44 @@ // After the relaxation we no longer call __tls_get_addr and should skip both // relocations to not create a false dependence on __tls_get_addr being // defined. - if (Type == R_PPC64_TLSGD || Type == R_PPC64_TLSLD) + if (type == R_PPC64_TLSGD || type == R_PPC64_TLSLD) return 2; return 1; } -static uint32_t getEFlags(InputFile *File) { - if (Config->EKind == ELF64BEKind) - return cast>(File)->getObj().getHeader()->e_flags; - return cast>(File)->getObj().getHeader()->e_flags; +static uint32_t getEFlags(InputFile *file) { + if (config->ekind == ELF64BEKind) + return cast>(file)->getObj().getHeader()->e_flags; + return cast>(file)->getObj().getHeader()->e_flags; } // This file implements v2 ABI. This function makes sure that all // object files have v2 or an unspecified version as an ABI version. uint32_t PPC64::calcEFlags() const { - for (InputFile *F : ObjectFiles) { - uint32_t Flag = getEFlags(F); - if (Flag == 1) - error(toString(F) + ": ABI version 1 is not supported"); - else if (Flag > 2) - error(toString(F) + ": unrecognized e_flags: " + Twine(Flag)); + for (InputFile *f : objectFiles) { + uint32_t flag = getEFlags(f); + if (flag == 1) + error(toString(f) + ": ABI version 1 is not supported"); + else if (flag > 2) + error(toString(f) + ": unrecognized e_flags: " + Twine(flag)); } return 2; } -void PPC64::relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC64_TOC16_HA: // Convert "addis reg, 2, .LC0@toc@h" to "addis reg, 2, var@toc@h" or "nop". - relocateOne(Loc, Type, Val); + relocateOne(loc, type, val); break; case R_PPC64_TOC16_LO_DS: { // Convert "ld reg, .LC0@toc@l(reg)" to "addi reg, reg, var@toc@l" or // "addi reg, 2, var@toc". - uint32_t Insn = readFromHalf16(Loc); - if (getPrimaryOpCode(Insn) != LD) + uint32_t insn = readFromHalf16(loc); + if (getPrimaryOpCode(insn) != LD) error("expected a 'ld' for got-indirect to toc-relative relaxing"); - writeFromHalf16(Loc, (Insn & 0x03ffffff) | 0x38000000); - relocateOne(Loc, R_PPC64_TOC16_LO, Val); + writeFromHalf16(loc, (insn & 0x03ffffff) | 0x38000000); + relocateOne(loc, R_PPC64_TOC16_LO, val); break; } default: @@ -375,7 +375,7 @@ } } -void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void PPC64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement. // The general dynamic code sequence for a global `x` will look like: // Instruction Relocation Symbol @@ -391,30 +391,30 @@ // bl __tls_get_addr(x@tlsgd) into nop // nop into addi r3, r3, x@tprel@l - switch (Type) { + switch (type) { case R_PPC64_GOT_TLSGD16_HA: - writeFromHalf16(Loc, 0x60000000); // nop + writeFromHalf16(loc, 0x60000000); // nop break; case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: - writeFromHalf16(Loc, 0x3c6d0000); // addis r3, r13 - relocateOne(Loc, R_PPC64_TPREL16_HA, Val); + writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13 + relocateOne(loc, R_PPC64_TPREL16_HA, val); break; case R_PPC64_TLSGD: - write32(Loc, 0x60000000); // nop - write32(Loc + 4, 0x38630000); // addi r3, r3 + write32(loc, 0x60000000); // nop + write32(loc + 4, 0x38630000); // addi r3, r3 // Since we are relocating a half16 type relocation and Loc + 4 points to // the start of an instruction we need to advance the buffer by an extra // 2 bytes on BE. - relocateOne(Loc + 4 + (Config->EKind == ELF64BEKind ? 2 : 0), - R_PPC64_TPREL16_LO, Val); + relocateOne(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0), + R_PPC64_TPREL16_LO, val); break; default: llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); } } -void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement. // The local dynamic code sequence for a global `x` will look like: // Instruction Relocation Symbol @@ -430,16 +430,16 @@ // bl __tls_get_addr(x@tlsgd) into nop // nop into addi r3, r3, 4096 - switch (Type) { + switch (type) { case R_PPC64_GOT_TLSLD16_HA: - writeFromHalf16(Loc, 0x60000000); // nop + writeFromHalf16(loc, 0x60000000); // nop break; case R_PPC64_GOT_TLSLD16_LO: - writeFromHalf16(Loc, 0x3c6d0000); // addis r3, r13, 0 + writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13, 0 break; case R_PPC64_TLSLD: - write32(Loc, 0x60000000); // nop - write32(Loc + 4, 0x38631000); // addi r3, r3, 4096 + write32(loc, 0x60000000); // nop + write32(loc + 4, 0x38631000); // addi r3, r3, 4096 break; case R_PPC64_DTPREL16: case R_PPC64_DTPREL16_HA: @@ -447,15 +447,15 @@ case R_PPC64_DTPREL16_DS: case R_PPC64_DTPREL16_LO: case R_PPC64_DTPREL16_LO_DS: - relocateOne(Loc, Type, Val); + relocateOne(loc, type, val); break; default: llvm_unreachable("unsupported relocation for TLS LD to LE relaxation"); } } -unsigned elf::getPPCDFormOp(unsigned SecondaryOp) { - switch (SecondaryOp) { +unsigned elf::getPPCDFormOp(unsigned secondaryOp) { + switch (secondaryOp) { case LBZX: return LBZ; case LHZX: @@ -479,7 +479,7 @@ } } -void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { // The initial exec code sequence for a global `x` will look like: // Instruction Relocation Symbol // addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x @@ -499,28 +499,28 @@ // instruction, if we are accessing memory it will use any of the X-form // indexed load or store instructions. - unsigned Offset = (Config->EKind == ELF64BEKind) ? 2 : 0; - switch (Type) { + unsigned offset = (config->ekind == ELF64BEKind) ? 2 : 0; + switch (type) { case R_PPC64_GOT_TPREL16_HA: - write32(Loc - Offset, 0x60000000); // nop + write32(loc - offset, 0x60000000); // nop break; case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_TPREL16_DS: { - uint32_t RegNo = read32(Loc - Offset) & 0x03E00000; // bits 6-10 - write32(Loc - Offset, 0x3C0D0000 | RegNo); // addis RegNo, r13 - relocateOne(Loc, R_PPC64_TPREL16_HA, Val); + uint32_t regNo = read32(loc - offset) & 0x03E00000; // bits 6-10 + write32(loc - offset, 0x3C0D0000 | regNo); // addis RegNo, r13 + relocateOne(loc, R_PPC64_TPREL16_HA, val); break; } case R_PPC64_TLS: { - uint32_t PrimaryOp = getPrimaryOpCode(read32(Loc)); - if (PrimaryOp != 31) + uint32_t primaryOp = getPrimaryOpCode(read32(loc)); + if (primaryOp != 31) error("unrecognized instruction for IE to LE R_PPC64_TLS"); - uint32_t SecondaryOp = (read32(Loc) & 0x000007FE) >> 1; // bits 21-30 - uint32_t DFormOp = getPPCDFormOp(SecondaryOp); - if (DFormOp == 0) + uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30 + uint32_t dFormOp = getPPCDFormOp(secondaryOp); + if (dFormOp == 0) error("unrecognized instruction for IE to LE R_PPC64_TLS"); - write32(Loc, ((DFormOp << 26) | (read32(Loc) & 0x03FFFFFF))); - relocateOne(Loc + Offset, R_PPC64_TPREL16_LO, Val); + write32(loc, ((dFormOp << 26) | (read32(loc) & 0x03FFFFFF))); + relocateOne(loc + offset, R_PPC64_TPREL16_LO, val); break; } default: @@ -529,9 +529,9 @@ } } -RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: @@ -546,7 +546,7 @@ return R_GOTREL; case R_PPC64_TOC16_HA: case R_PPC64_TOC16_LO_DS: - return Config->TocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL; + return config->tocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL; case R_PPC64_TOC: return R_PPC64_TOCBASE; case R_PPC64_REL14: @@ -611,121 +611,121 @@ } } -RelType PPC64::getDynRel(RelType Type) const { - if (Type == R_PPC64_ADDR64 || Type == R_PPC64_TOC) +RelType PPC64::getDynRel(RelType type) const { + if (type == R_PPC64_ADDR64 || type == R_PPC64_TOC) return R_PPC64_ADDR64; return R_PPC64_NONE; } -void PPC64::writeGotHeader(uint8_t *Buf) const { - write64(Buf, getPPC64TocBase()); +void PPC64::writeGotHeader(uint8_t *buf) const { + write64(buf, getPPC64TocBase()); } -void PPC64::writePltHeader(uint8_t *Buf) const { +void PPC64::writePltHeader(uint8_t *buf) const { // The generic resolver stub goes first. - write32(Buf + 0, 0x7c0802a6); // mflr r0 - write32(Buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8> - write32(Buf + 8, 0x7d6802a6); // mflr r11 - write32(Buf + 12, 0x7c0803a6); // mtlr r0 - write32(Buf + 16, 0x7d8b6050); // subf r12, r11, r12 - write32(Buf + 20, 0x380cffcc); // subi r0,r12,52 - write32(Buf + 24, 0x7800f082); // srdi r0,r0,62,2 - write32(Buf + 28, 0xe98b002c); // ld r12,44(r11) - write32(Buf + 32, 0x7d6c5a14); // add r11,r12,r11 - write32(Buf + 36, 0xe98b0000); // ld r12,0(r11) - write32(Buf + 40, 0xe96b0008); // ld r11,8(r11) - write32(Buf + 44, 0x7d8903a6); // mtctr r12 - write32(Buf + 48, 0x4e800420); // bctr + write32(buf + 0, 0x7c0802a6); // mflr r0 + write32(buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8> + write32(buf + 8, 0x7d6802a6); // mflr r11 + write32(buf + 12, 0x7c0803a6); // mtlr r0 + write32(buf + 16, 0x7d8b6050); // subf r12, r11, r12 + write32(buf + 20, 0x380cffcc); // subi r0,r12,52 + write32(buf + 24, 0x7800f082); // srdi r0,r0,62,2 + write32(buf + 28, 0xe98b002c); // ld r12,44(r11) + write32(buf + 32, 0x7d6c5a14); // add r11,r12,r11 + write32(buf + 36, 0xe98b0000); // ld r12,0(r11) + write32(buf + 40, 0xe96b0008); // ld r11,8(r11) + write32(buf + 44, 0x7d8903a6); // mtctr r12 + write32(buf + 48, 0x4e800420); // bctr // The 'bcl' instruction will set the link register to the address of the // following instruction ('mflr r11'). Here we store the offset from that // instruction to the first entry in the GotPlt section. - int64_t GotPltOffset = In.GotPlt->getVA() - (In.Plt->getVA() + 8); - write64(Buf + 52, GotPltOffset); + int64_t gotPltOffset = in.gotPlt->getVA() - (in.plt->getVA() + 8); + write64(buf + 52, gotPltOffset); } -void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - int32_t Offset = PltHeaderSize + Index * PltEntrySize; +void PPC64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + int32_t offset = pltHeaderSize + index * pltEntrySize; // bl __glink_PLTresolve - write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc)); + write32(buf, 0x48000000 | ((-offset) & 0x03FFFFFc)); } -static std::pair toAddr16Rel(RelType Type, uint64_t Val) { +static std::pair toAddr16Rel(RelType type, uint64_t val) { // Relocations relative to the toc-base need to be adjusted by the Toc offset. - uint64_t TocBiasedVal = Val - PPC64TocOffset; + uint64_t tocBiasedVal = val - ppc64TocOffset; // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset. - uint64_t DTPBiasedVal = Val - DynamicThreadPointerOffset; + uint64_t dtpBiasedVal = val - dynamicThreadPointerOffset; - switch (Type) { + switch (type) { // TOC biased relocation. case R_PPC64_GOT16: case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSLD16: case R_PPC64_TOC16: - return {R_PPC64_ADDR16, TocBiasedVal}; + return {R_PPC64_ADDR16, tocBiasedVal}; case R_PPC64_GOT16_DS: case R_PPC64_TOC16_DS: case R_PPC64_GOT_TPREL16_DS: case R_PPC64_GOT_DTPREL16_DS: - return {R_PPC64_ADDR16_DS, TocBiasedVal}; + return {R_PPC64_ADDR16_DS, tocBiasedVal}; case R_PPC64_GOT16_HA: case R_PPC64_GOT_TLSGD16_HA: case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TPREL16_HA: case R_PPC64_GOT_DTPREL16_HA: case R_PPC64_TOC16_HA: - return {R_PPC64_ADDR16_HA, TocBiasedVal}; + return {R_PPC64_ADDR16_HA, tocBiasedVal}; case R_PPC64_GOT16_HI: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_GOT_DTPREL16_HI: case R_PPC64_TOC16_HI: - return {R_PPC64_ADDR16_HI, TocBiasedVal}; + return {R_PPC64_ADDR16_HI, tocBiasedVal}; case R_PPC64_GOT16_LO: case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_TOC16_LO: - return {R_PPC64_ADDR16_LO, TocBiasedVal}; + return {R_PPC64_ADDR16_LO, tocBiasedVal}; case R_PPC64_GOT16_LO_DS: case R_PPC64_TOC16_LO_DS: case R_PPC64_GOT_TPREL16_LO_DS: case R_PPC64_GOT_DTPREL16_LO_DS: - return {R_PPC64_ADDR16_LO_DS, TocBiasedVal}; + return {R_PPC64_ADDR16_LO_DS, tocBiasedVal}; // Dynamic Thread pointer biased relocation types. case R_PPC64_DTPREL16: - return {R_PPC64_ADDR16, DTPBiasedVal}; + return {R_PPC64_ADDR16, dtpBiasedVal}; case R_PPC64_DTPREL16_DS: - return {R_PPC64_ADDR16_DS, DTPBiasedVal}; + return {R_PPC64_ADDR16_DS, dtpBiasedVal}; case R_PPC64_DTPREL16_HA: - return {R_PPC64_ADDR16_HA, DTPBiasedVal}; + return {R_PPC64_ADDR16_HA, dtpBiasedVal}; case R_PPC64_DTPREL16_HI: - return {R_PPC64_ADDR16_HI, DTPBiasedVal}; + return {R_PPC64_ADDR16_HI, dtpBiasedVal}; case R_PPC64_DTPREL16_HIGHER: - return {R_PPC64_ADDR16_HIGHER, DTPBiasedVal}; + return {R_PPC64_ADDR16_HIGHER, dtpBiasedVal}; case R_PPC64_DTPREL16_HIGHERA: - return {R_PPC64_ADDR16_HIGHERA, DTPBiasedVal}; + return {R_PPC64_ADDR16_HIGHERA, dtpBiasedVal}; case R_PPC64_DTPREL16_HIGHEST: - return {R_PPC64_ADDR16_HIGHEST, DTPBiasedVal}; + return {R_PPC64_ADDR16_HIGHEST, dtpBiasedVal}; case R_PPC64_DTPREL16_HIGHESTA: - return {R_PPC64_ADDR16_HIGHESTA, DTPBiasedVal}; + return {R_PPC64_ADDR16_HIGHESTA, dtpBiasedVal}; case R_PPC64_DTPREL16_LO: - return {R_PPC64_ADDR16_LO, DTPBiasedVal}; + return {R_PPC64_ADDR16_LO, dtpBiasedVal}; case R_PPC64_DTPREL16_LO_DS: - return {R_PPC64_ADDR16_LO_DS, DTPBiasedVal}; + return {R_PPC64_ADDR16_LO_DS, dtpBiasedVal}; case R_PPC64_DTPREL64: - return {R_PPC64_ADDR64, DTPBiasedVal}; + return {R_PPC64_ADDR64, dtpBiasedVal}; default: - return {Type, Val}; + return {type, val}; } } -static bool isTocOptType(RelType Type) { - switch (Type) { +static bool isTocOptType(RelType type) { + switch (type) { case R_PPC64_GOT16_HA: case R_PPC64_GOT16_LO_DS: case R_PPC64_TOC16_HA: @@ -737,69 +737,69 @@ } } -void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { +void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { // We need to save the original relocation type to use in diagnostics, and // use the original type to determine if we should toc-optimize the // instructions being relocated. - RelType OriginalType = Type; - bool ShouldTocOptimize = isTocOptType(Type); + RelType originalType = type; + bool shouldTocOptimize = isTocOptType(type); // For dynamic thread pointer relative, toc-relative, and got-indirect // relocations, proceed in terms of the corresponding ADDR16 relocation type. - std::tie(Type, Val) = toAddr16Rel(Type, Val); + std::tie(type, val) = toAddr16Rel(type, val); - switch (Type) { + switch (type) { case R_PPC64_ADDR14: { - checkAlignment(Loc, Val, 4, Type); + checkAlignment(loc, val, 4, type); // Preserve the AA/LK bits in the branch instruction - uint8_t AALK = Loc[3]; - write16(Loc + 2, (AALK & 3) | (Val & 0xfffc)); + uint8_t aalk = loc[3]; + write16(loc + 2, (aalk & 3) | (val & 0xfffc)); break; } case R_PPC64_ADDR16: - checkIntUInt(Loc, Val, 16, OriginalType); - write16(Loc, Val); + checkIntUInt(loc, val, 16, originalType); + write16(loc, val); break; case R_PPC64_ADDR32: - checkIntUInt(Loc, Val, 32, OriginalType); - write32(Loc, Val); + checkIntUInt(loc, val, 32, originalType); + write32(loc, val); break; case R_PPC64_ADDR16_DS: case R_PPC64_TPREL16_DS: { - checkInt(Loc, Val, 16, OriginalType); + checkInt(loc, val, 16, originalType); // DQ-form instructions use bits 28-31 as part of the instruction encoding // DS-form instructions only use bits 30-31. - uint16_t Mask = isDQFormInstruction(readFromHalf16(Loc)) ? 0xf : 0x3; - checkAlignment(Loc, lo(Val), Mask + 1, OriginalType); - write16(Loc, (read16(Loc) & Mask) | lo(Val)); + uint16_t mask = isDQFormInstruction(readFromHalf16(loc)) ? 0xf : 0x3; + checkAlignment(loc, lo(val), mask + 1, originalType); + write16(loc, (read16(loc) & mask) | lo(val)); } break; case R_PPC64_ADDR16_HA: case R_PPC64_REL16_HA: case R_PPC64_TPREL16_HA: - if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) - writeFromHalf16(Loc, 0x60000000); + if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) + writeFromHalf16(loc, 0x60000000); else - write16(Loc, ha(Val)); + write16(loc, ha(val)); break; case R_PPC64_ADDR16_HI: case R_PPC64_REL16_HI: case R_PPC64_TPREL16_HI: - write16(Loc, hi(Val)); + write16(loc, hi(val)); break; case R_PPC64_ADDR16_HIGHER: case R_PPC64_TPREL16_HIGHER: - write16(Loc, higher(Val)); + write16(loc, higher(val)); break; case R_PPC64_ADDR16_HIGHERA: case R_PPC64_TPREL16_HIGHERA: - write16(Loc, highera(Val)); + write16(loc, highera(val)); break; case R_PPC64_ADDR16_HIGHEST: case R_PPC64_TPREL16_HIGHEST: - write16(Loc, highest(Val)); + write16(loc, highest(val)); break; case R_PPC64_ADDR16_HIGHESTA: case R_PPC64_TPREL16_HIGHESTA: - write16(Loc, highesta(Val)); + write16(loc, highesta(val)); break; case R_PPC64_ADDR16_LO: case R_PPC64_REL16_LO: @@ -807,93 +807,93 @@ // When the high-adjusted part of a toc relocation evalutes to 0, it is // changed into a nop. The lo part then needs to be updated to use the // toc-pointer register r2, as the base register. - if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) { - uint32_t Insn = readFromHalf16(Loc); - if (isInstructionUpdateForm(Insn)) - error(getErrorLocation(Loc) + + if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) { + uint32_t insn = readFromHalf16(loc); + if (isInstructionUpdateForm(insn)) + error(getErrorLocation(loc) + "can't toc-optimize an update instruction: 0x" + - utohexstr(Insn)); - writeFromHalf16(Loc, (Insn & 0xffe00000) | 0x00020000 | lo(Val)); + utohexstr(insn)); + writeFromHalf16(loc, (insn & 0xffe00000) | 0x00020000 | lo(val)); } else { - write16(Loc, lo(Val)); + write16(loc, lo(val)); } break; case R_PPC64_ADDR16_LO_DS: case R_PPC64_TPREL16_LO_DS: { // DQ-form instructions use bits 28-31 as part of the instruction encoding // DS-form instructions only use bits 30-31. - uint32_t Insn = readFromHalf16(Loc); - uint16_t Mask = isDQFormInstruction(Insn) ? 0xf : 0x3; - checkAlignment(Loc, lo(Val), Mask + 1, OriginalType); - if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) { + uint32_t insn = readFromHalf16(loc); + uint16_t mask = isDQFormInstruction(insn) ? 0xf : 0x3; + checkAlignment(loc, lo(val), mask + 1, originalType); + if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) { // When the high-adjusted part of a toc relocation evalutes to 0, it is // changed into a nop. The lo part then needs to be updated to use the toc // pointer register r2, as the base register. - if (isInstructionUpdateForm(Insn)) - error(getErrorLocation(Loc) + + if (isInstructionUpdateForm(insn)) + error(getErrorLocation(loc) + "Can't toc-optimize an update instruction: 0x" + - Twine::utohexstr(Insn)); - Insn &= 0xffe00000 | Mask; - writeFromHalf16(Loc, Insn | 0x00020000 | lo(Val)); + Twine::utohexstr(insn)); + insn &= 0xffe00000 | mask; + writeFromHalf16(loc, insn | 0x00020000 | lo(val)); } else { - write16(Loc, (read16(Loc) & Mask) | lo(Val)); + write16(loc, (read16(loc) & mask) | lo(val)); } } break; case R_PPC64_TPREL16: - checkInt(Loc, Val, 16, OriginalType); - write16(Loc, Val); + checkInt(loc, val, 16, originalType); + write16(loc, val); break; case R_PPC64_REL32: - checkInt(Loc, Val, 32, Type); - write32(Loc, Val); + checkInt(loc, val, 32, type); + write32(loc, val); break; case R_PPC64_ADDR64: case R_PPC64_REL64: case R_PPC64_TOC: - write64(Loc, Val); + write64(loc, val); break; case R_PPC64_REL14: { - uint32_t Mask = 0x0000FFFC; - checkInt(Loc, Val, 16, Type); - checkAlignment(Loc, Val, 4, Type); - write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); + uint32_t mask = 0x0000FFFC; + checkInt(loc, val, 16, type); + checkAlignment(loc, val, 4, type); + write32(loc, (read32(loc) & ~mask) | (val & mask)); break; } case R_PPC64_REL24: { - uint32_t Mask = 0x03FFFFFC; - checkInt(Loc, Val, 26, Type); - checkAlignment(Loc, Val, 4, Type); - write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); + uint32_t mask = 0x03FFFFFC; + checkInt(loc, val, 26, type); + checkAlignment(loc, val, 4, type); + write32(loc, (read32(loc) & ~mask) | (val & mask)); break; } case R_PPC64_DTPREL64: - write64(Loc, Val - DynamicThreadPointerOffset); + write64(loc, val - dynamicThreadPointerOffset); break; default: - error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); + error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); } } -bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { - if (Type != R_PPC64_REL14 && Type != R_PPC64_REL24) +bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { + if (type != R_PPC64_REL14 && type != R_PPC64_REL24) return false; // If a function is in the Plt it needs to be called with a call-stub. - if (S.isInPlt()) + if (s.isInPlt()) return true; // If a symbol is a weak undefined and we are compiling an executable // it doesn't need a range-extending thunk since it can't be called. - if (S.isUndefWeak() && !Config->Shared) + if (s.isUndefWeak() && !config->shared) return false; // If the offset exceeds the range of the branch type then it will need // a range-extending thunk. // See the comment in getRelocTargetVA() about R_PPC64_CALL. - return !inBranchRange(Type, BranchAddr, - S.getVA() + - getPPC64GlobalEntryToLocalEntryOffset(S.StOther)); + return !inBranchRange(type, branchAddr, + s.getVA() + + getPPC64GlobalEntryToLocalEntryOffset(s.stOther)); } uint32_t PPC64::getThunkSectionSpacing() const { @@ -904,22 +904,22 @@ return 0x2000000; } -bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { - int64_t Offset = Dst - Src; - if (Type == R_PPC64_REL14) - return isInt<16>(Offset); - if (Type == R_PPC64_REL24) - return isInt<26>(Offset); +bool PPC64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { + int64_t offset = dst - src; + if (type == R_PPC64_REL14) + return isInt<16>(offset); + if (type == R_PPC64_REL24) + return isInt<26>(offset); llvm_unreachable("unsupported relocation type used in branch"); } -RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - if (Expr == R_RELAX_TLS_GD_TO_IE) +RelExpr PPC64::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + if (expr == R_RELAX_TLS_GD_TO_IE) return R_RELAX_TLS_GD_TO_IE_GOT_OFF; - if (Expr == R_RELAX_TLS_LD_TO_LE) + if (expr == R_RELAX_TLS_LD_TO_LE) return R_RELAX_TLS_LD_TO_LE_ABS; - return Expr; + return expr; } // Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement. @@ -939,24 +939,24 @@ // thread pointer. // Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is // used as the relaxation hint for both steps 2 and 3. -void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void PPC64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_PPC64_GOT_TLSGD16_HA: // This is relaxed from addis rT, r2, sym@got@tlsgd@ha to // addis rT, r2, sym@got@tprel@ha. - relocateOne(Loc, R_PPC64_GOT_TPREL16_HA, Val); + relocateOne(loc, R_PPC64_GOT_TPREL16_HA, val); return; case R_PPC64_GOT_TLSGD16_LO: { // Relax from addi r3, rA, sym@got@tlsgd@l to // ld r3, sym@got@tprel@l(rA) - uint32_t RA = (readFromHalf16(Loc) & (0x1f << 16)); - writeFromHalf16(Loc, 0xe8600000 | RA); - relocateOne(Loc, R_PPC64_GOT_TPREL16_LO_DS, Val); + uint32_t ra = (readFromHalf16(loc) & (0x1f << 16)); + writeFromHalf16(loc, 0xe8600000 | ra); + relocateOne(loc, R_PPC64_GOT_TPREL16_LO_DS, val); return; } case R_PPC64_TLSGD: - write32(Loc, 0x60000000); // bl __tls_get_addr(sym@tlsgd) --> nop - write32(Loc + 4, 0x7c636A14); // nop --> add r3, r3, r13 + write32(loc, 0x60000000); // bl __tls_get_addr(sym@tlsgd) --> nop + write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13 return; default: llvm_unreachable("unsupported relocation for TLS GD to IE relaxation"); @@ -991,86 +991,86 @@ // pair by split-stack-size-adjust. // addis r12, r1, ha(-stack-frame size - split-stack-adjust-size) // addi r12, r12, l(-stack-frame size - split-stack-adjust-size) -bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const { +bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const { // If the caller has a global entry point adjust the buffer past it. The start // of the split-stack prologue will be at the local entry point. - Loc += getPPC64GlobalEntryToLocalEntryOffset(StOther); + loc += getPPC64GlobalEntryToLocalEntryOffset(stOther); // At the very least we expect to see a load of some split-stack data from the // tcb, and 2 instructions that calculate the ending stack address this // function will require. If there is not enough room for at least 3 // instructions it can't be a split-stack prologue. - if (Loc + 12 >= End) + if (loc + 12 >= end) return false; // First instruction must be `ld r0, -0x7000-64(r13)` - if (read32(Loc) != 0xe80d8fc0) + if (read32(loc) != 0xe80d8fc0) return false; - int16_t HiImm = 0; - int16_t LoImm = 0; + int16_t hiImm = 0; + int16_t loImm = 0; // First instruction can be either an addis if the frame size is larger then // 32K, or an addi if the size is less then 32K. - int32_t FirstInstr = read32(Loc + 4); - if (getPrimaryOpCode(FirstInstr) == 15) { - HiImm = FirstInstr & 0xFFFF; - } else if (getPrimaryOpCode(FirstInstr) == 14) { - LoImm = FirstInstr & 0xFFFF; + int32_t firstInstr = read32(loc + 4); + if (getPrimaryOpCode(firstInstr) == 15) { + hiImm = firstInstr & 0xFFFF; + } else if (getPrimaryOpCode(firstInstr) == 14) { + loImm = firstInstr & 0xFFFF; } else { return false; } // Second instruction is either an addi or a nop. If the first instruction was // an addi then LoImm is set and the second instruction must be a nop. - uint32_t SecondInstr = read32(Loc + 8); - if (!LoImm && getPrimaryOpCode(SecondInstr) == 14) { - LoImm = SecondInstr & 0xFFFF; - } else if (SecondInstr != 0x60000000) { + uint32_t secondInstr = read32(loc + 8); + if (!loImm && getPrimaryOpCode(secondInstr) == 14) { + loImm = secondInstr & 0xFFFF; + } else if (secondInstr != 0x60000000) { return false; } // The register operands of the first instruction should be the stack-pointer // (r1) as the input (RA) and r12 as the output (RT). If the second // instruction is not a nop, then it should use r12 as both input and output. - auto CheckRegOperands = [](uint32_t Instr, uint8_t ExpectedRT, - uint8_t ExpectedRA) { - return ((Instr & 0x3E00000) >> 21 == ExpectedRT) && - ((Instr & 0x1F0000) >> 16 == ExpectedRA); + auto checkRegOperands = [](uint32_t instr, uint8_t expectedRT, + uint8_t expectedRA) { + return ((instr & 0x3E00000) >> 21 == expectedRT) && + ((instr & 0x1F0000) >> 16 == expectedRA); }; - if (!CheckRegOperands(FirstInstr, 12, 1)) + if (!checkRegOperands(firstInstr, 12, 1)) return false; - if (SecondInstr != 0x60000000 && !CheckRegOperands(SecondInstr, 12, 12)) + if (secondInstr != 0x60000000 && !checkRegOperands(secondInstr, 12, 12)) return false; - int32_t StackFrameSize = (HiImm * 65536) + LoImm; + int32_t stackFrameSize = (hiImm * 65536) + loImm; // Check that the adjusted size doesn't overflow what we can represent with 2 // instructions. - if (StackFrameSize < Config->SplitStackAdjustSize + INT32_MIN) { - error(getErrorLocation(Loc) + "split-stack prologue adjustment overflows"); + if (stackFrameSize < config->splitStackAdjustSize + INT32_MIN) { + error(getErrorLocation(loc) + "split-stack prologue adjustment overflows"); return false; } - int32_t AdjustedStackFrameSize = - StackFrameSize - Config->SplitStackAdjustSize; + int32_t adjustedStackFrameSize = + stackFrameSize - config->splitStackAdjustSize; - LoImm = AdjustedStackFrameSize & 0xFFFF; - HiImm = (AdjustedStackFrameSize + 0x8000) >> 16; - if (HiImm) { - write32(Loc + 4, 0x3D810000 | (uint16_t)HiImm); + loImm = adjustedStackFrameSize & 0xFFFF; + hiImm = (adjustedStackFrameSize + 0x8000) >> 16; + if (hiImm) { + write32(loc + 4, 0x3D810000 | (uint16_t)hiImm); // If the low immediate is zero the second instruction will be a nop. - SecondInstr = LoImm ? 0x398C0000 | (uint16_t)LoImm : 0x60000000; - write32(Loc + 8, SecondInstr); + secondInstr = loImm ? 0x398C0000 | (uint16_t)loImm : 0x60000000; + write32(loc + 8, secondInstr); } else { // addi r12, r1, imm - write32(Loc + 4, (0x39810000) | (uint16_t)LoImm); - write32(Loc + 8, 0x60000000); + write32(loc + 4, (0x39810000) | (uint16_t)loImm); + write32(loc + 8, 0x60000000); } return true; } TargetInfo *elf::getPPC64TargetInfo() { - static PPC64 Target; - return &Target; + static PPC64 target; + return ⌖ } Index: lld/trunk/ELF/Arch/RISCV.cpp =================================================================== --- lld/trunk/ELF/Arch/RISCV.cpp +++ lld/trunk/ELF/Arch/RISCV.cpp @@ -23,20 +23,20 @@ public: RISCV(); uint32_t calcEFlags() const override; - void writeGotHeader(uint8_t *Buf) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - RelType getDynRel(RelType Type) const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + void writeGotHeader(uint8_t *buf) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + RelType getDynRel(RelType type) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; }; } // end anonymous namespace -const uint64_t DTPOffset = 0x800; +const uint64_t dtpOffset = 0x800; enum Op { ADDI = 0x13, @@ -56,91 +56,91 @@ X_T3 = 28, }; -static uint32_t hi20(uint32_t Val) { return (Val + 0x800) >> 12; } -static uint32_t lo12(uint32_t Val) { return Val & 4095; } +static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; } +static uint32_t lo12(uint32_t val) { return val & 4095; } -static uint32_t itype(uint32_t Op, uint32_t Rd, uint32_t Rs1, uint32_t Imm) { - return Op | (Rd << 7) | (Rs1 << 15) | (Imm << 20); +static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) { + return op | (rd << 7) | (rs1 << 15) | (imm << 20); } -static uint32_t rtype(uint32_t Op, uint32_t Rd, uint32_t Rs1, uint32_t Rs2) { - return Op | (Rd << 7) | (Rs1 << 15) | (Rs2 << 20); +static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) { + return op | (rd << 7) | (rs1 << 15) | (rs2 << 20); } -static uint32_t utype(uint32_t Op, uint32_t Rd, uint32_t Imm) { - return Op | (Rd << 7) | (Imm << 12); +static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) { + return op | (rd << 7) | (imm << 12); } RISCV::RISCV() { - CopyRel = R_RISCV_COPY; - NoneRel = R_RISCV_NONE; - PltRel = R_RISCV_JUMP_SLOT; - RelativeRel = R_RISCV_RELATIVE; - if (Config->Is64) { - SymbolicRel = R_RISCV_64; - TlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; - TlsOffsetRel = R_RISCV_TLS_DTPREL64; - TlsGotRel = R_RISCV_TLS_TPREL64; + copyRel = R_RISCV_COPY; + noneRel = R_RISCV_NONE; + pltRel = R_RISCV_JUMP_SLOT; + relativeRel = R_RISCV_RELATIVE; + if (config->is64) { + symbolicRel = R_RISCV_64; + tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64; + tlsOffsetRel = R_RISCV_TLS_DTPREL64; + tlsGotRel = R_RISCV_TLS_TPREL64; } else { - SymbolicRel = R_RISCV_32; - TlsModuleIndexRel = R_RISCV_TLS_DTPMOD32; - TlsOffsetRel = R_RISCV_TLS_DTPREL32; - TlsGotRel = R_RISCV_TLS_TPREL32; + symbolicRel = R_RISCV_32; + tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32; + tlsOffsetRel = R_RISCV_TLS_DTPREL32; + tlsGotRel = R_RISCV_TLS_TPREL32; } - GotRel = SymbolicRel; + gotRel = symbolicRel; // .got[0] = _DYNAMIC - GotBaseSymInGotPlt = false; - GotHeaderEntriesNum = 1; + gotBaseSymInGotPlt = false; + gotHeaderEntriesNum = 1; // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map - GotPltHeaderEntriesNum = 2; + gotPltHeaderEntriesNum = 2; - PltEntrySize = 16; - PltHeaderSize = 32; + pltEntrySize = 16; + pltHeaderSize = 32; } -static uint32_t getEFlags(InputFile *F) { - if (Config->Is64) - return cast>(F)->getObj().getHeader()->e_flags; - return cast>(F)->getObj().getHeader()->e_flags; +static uint32_t getEFlags(InputFile *f) { + if (config->is64) + return cast>(f)->getObj().getHeader()->e_flags; + return cast>(f)->getObj().getHeader()->e_flags; } uint32_t RISCV::calcEFlags() const { - assert(!ObjectFiles.empty()); + assert(!objectFiles.empty()); - uint32_t Target = getEFlags(ObjectFiles.front()); + uint32_t target = getEFlags(objectFiles.front()); - for (InputFile *F : ObjectFiles) { - uint32_t EFlags = getEFlags(F); - if (EFlags & EF_RISCV_RVC) - Target |= EF_RISCV_RVC; + for (InputFile *f : objectFiles) { + uint32_t eflags = getEFlags(f); + if (eflags & EF_RISCV_RVC) + target |= EF_RISCV_RVC; - if ((EFlags & EF_RISCV_FLOAT_ABI) != (Target & EF_RISCV_FLOAT_ABI)) - error(toString(F) + + if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI)) + error(toString(f) + ": cannot link object files with different floating-point ABI"); - if ((EFlags & EF_RISCV_RVE) != (Target & EF_RISCV_RVE)) - error(toString(F) + + if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE)) + error(toString(f) + ": cannot link object files with different EF_RISCV_RVE"); } - return Target; + return target; } -void RISCV::writeGotHeader(uint8_t *Buf) const { - if (Config->Is64) - write64le(Buf, Main->Dynamic->getVA()); +void RISCV::writeGotHeader(uint8_t *buf) const { + if (config->is64) + write64le(buf, mainPart->dynamic->getVA()); else - write32le(Buf, Main->Dynamic->getVA()); + write32le(buf, mainPart->dynamic->getVA()); } -void RISCV::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - if (Config->Is64) - write64le(Buf, In.Plt->getVA()); +void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const { + if (config->is64) + write64le(buf, in.plt->getVA()); else - write32le(Buf, In.Plt->getVA()); + write32le(buf, in.plt->getVA()); } -void RISCV::writePltHeader(uint8_t *Buf) const { +void RISCV::writePltHeader(uint8_t *buf) const { // 1: auipc t2, %pcrel_hi(.got.plt) // sub t1, t1, t3 // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve @@ -149,40 +149,40 @@ // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0] // l[wd] t0, Wordsize(t0); t0 = link_map // jr t3 - uint32_t Offset = In.GotPlt->getVA() - In.Plt->getVA(); - uint32_t Load = Config->Is64 ? LD : LW; - write32le(Buf + 0, utype(AUIPC, X_T2, hi20(Offset))); - write32le(Buf + 4, rtype(SUB, X_T1, X_T1, X_T3)); - write32le(Buf + 8, itype(Load, X_T3, X_T2, lo12(Offset))); - write32le(Buf + 12, itype(ADDI, X_T1, X_T1, -Target->PltHeaderSize - 12)); - write32le(Buf + 16, itype(ADDI, X_T0, X_T2, lo12(Offset))); - write32le(Buf + 20, itype(SRLI, X_T1, X_T1, Config->Is64 ? 1 : 2)); - write32le(Buf + 24, itype(Load, X_T0, X_T0, Config->Wordsize)); - write32le(Buf + 28, itype(JALR, 0, X_T3, 0)); + uint32_t offset = in.gotPlt->getVA() - in.plt->getVA(); + uint32_t load = config->is64 ? LD : LW; + write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset))); + write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3)); + write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset))); + write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12)); + write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset))); + write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2)); + write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize)); + write32le(buf + 28, itype(JALR, 0, X_T3, 0)); } -void RISCV::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { +void RISCV::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { // 1: auipc t3, %pcrel_hi(f@.got.plt) // l[wd] t3, %pcrel_lo(1b)(t3) // jalr t1, t3 // nop - uint32_t Offset = GotPltEntryAddr - PltEntryAddr; - write32le(Buf + 0, utype(AUIPC, X_T3, hi20(Offset))); - write32le(Buf + 4, itype(Config->Is64 ? LD : LW, X_T3, X_T3, lo12(Offset))); - write32le(Buf + 8, itype(JALR, X_T1, X_T3, 0)); - write32le(Buf + 12, itype(ADDI, 0, 0, 0)); + uint32_t offset = gotPltEntryAddr - pltEntryAddr; + write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset))); + write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset))); + write32le(buf + 8, itype(JALR, X_T1, X_T3, 0)); + write32le(buf + 12, itype(ADDI, 0, 0, 0)); } -RelType RISCV::getDynRel(RelType Type) const { - return Type == Target->SymbolicRel ? Type +RelType RISCV::getDynRel(RelType type) const { + return type == target->symbolicRel ? type : static_cast(R_RISCV_NONE); } -RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_RISCV_ADD8: case R_RISCV_ADD16: case R_RISCV_ADD32: @@ -215,7 +215,7 @@ case R_RISCV_TLS_GD_HI20: return R_TLSGD_PC; case R_RISCV_TLS_GOT_HI20: - Config->HasStaticTlsModel = true; + config->hasStaticTlsModel = true; return R_GOT_PC; case R_RISCV_TPREL_HI20: case R_RISCV_TPREL_LO12_I: @@ -231,106 +231,106 @@ } // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63. -static uint32_t extractBits(uint64_t V, uint32_t Begin, uint32_t End) { - return (V & ((1ULL << (Begin + 1)) - 1)) >> End; +static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) { + return (v & ((1ULL << (begin + 1)) - 1)) >> end; } -void RISCV::relocateOne(uint8_t *Loc, const RelType Type, - const uint64_t Val) const { - const unsigned Bits = Config->Wordsize * 8; +void RISCV::relocateOne(uint8_t *loc, const RelType type, + const uint64_t val) const { + const unsigned bits = config->wordsize * 8; - switch (Type) { + switch (type) { case R_RISCV_32: - write32le(Loc, Val); + write32le(loc, val); return; case R_RISCV_64: - write64le(Loc, Val); + write64le(loc, val); return; case R_RISCV_RVC_BRANCH: { - checkInt(Loc, static_cast(Val) >> 1, 8, Type); - checkAlignment(Loc, Val, 2, Type); - uint16_t Insn = read16le(Loc) & 0xE383; - uint16_t Imm8 = extractBits(Val, 8, 8) << 12; - uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10; - uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5; - uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3; - uint16_t Imm5 = extractBits(Val, 5, 5) << 2; - Insn |= Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5; + checkInt(loc, static_cast(val) >> 1, 8, type); + checkAlignment(loc, val, 2, type); + uint16_t insn = read16le(loc) & 0xE383; + uint16_t imm8 = extractBits(val, 8, 8) << 12; + uint16_t imm4_3 = extractBits(val, 4, 3) << 10; + uint16_t imm7_6 = extractBits(val, 7, 6) << 5; + uint16_t imm2_1 = extractBits(val, 2, 1) << 3; + uint16_t imm5 = extractBits(val, 5, 5) << 2; + insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5; - write16le(Loc, Insn); + write16le(loc, insn); return; } case R_RISCV_RVC_JUMP: { - checkInt(Loc, static_cast(Val) >> 1, 11, Type); - checkAlignment(Loc, Val, 2, Type); - uint16_t Insn = read16le(Loc) & 0xE003; - uint16_t Imm11 = extractBits(Val, 11, 11) << 12; - uint16_t Imm4 = extractBits(Val, 4, 4) << 11; - uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9; - uint16_t Imm10 = extractBits(Val, 10, 10) << 8; - uint16_t Imm6 = extractBits(Val, 6, 6) << 7; - uint16_t Imm7 = extractBits(Val, 7, 7) << 6; - uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3; - uint16_t Imm5 = extractBits(Val, 5, 5) << 2; - Insn |= Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5; + checkInt(loc, static_cast(val) >> 1, 11, type); + checkAlignment(loc, val, 2, type); + uint16_t insn = read16le(loc) & 0xE003; + uint16_t imm11 = extractBits(val, 11, 11) << 12; + uint16_t imm4 = extractBits(val, 4, 4) << 11; + uint16_t imm9_8 = extractBits(val, 9, 8) << 9; + uint16_t imm10 = extractBits(val, 10, 10) << 8; + uint16_t imm6 = extractBits(val, 6, 6) << 7; + uint16_t imm7 = extractBits(val, 7, 7) << 6; + uint16_t imm3_1 = extractBits(val, 3, 1) << 3; + uint16_t imm5 = extractBits(val, 5, 5) << 2; + insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5; - write16le(Loc, Insn); + write16le(loc, insn); return; } case R_RISCV_RVC_LUI: { - int64_t Imm = SignExtend64(Val + 0x800, Bits) >> 12; - checkInt(Loc, Imm, 6, Type); - if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` - write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000); + int64_t imm = SignExtend64(val + 0x800, bits) >> 12; + checkInt(loc, imm, 6, type); + if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` + write16le(loc, (read16le(loc) & 0x0F83) | 0x4000); } else { - uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12; - uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2; - write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12); + uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12; + uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2; + write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12); } return; } case R_RISCV_JAL: { - checkInt(Loc, static_cast(Val) >> 1, 20, Type); - checkAlignment(Loc, Val, 2, Type); + checkInt(loc, static_cast(val) >> 1, 20, type); + checkAlignment(loc, val, 2, type); - uint32_t Insn = read32le(Loc) & 0xFFF; - uint32_t Imm20 = extractBits(Val, 20, 20) << 31; - uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21; - uint32_t Imm11 = extractBits(Val, 11, 11) << 20; - uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12; - Insn |= Imm20 | Imm10_1 | Imm11 | Imm19_12; + uint32_t insn = read32le(loc) & 0xFFF; + uint32_t imm20 = extractBits(val, 20, 20) << 31; + uint32_t imm10_1 = extractBits(val, 10, 1) << 21; + uint32_t imm11 = extractBits(val, 11, 11) << 20; + uint32_t imm19_12 = extractBits(val, 19, 12) << 12; + insn |= imm20 | imm10_1 | imm11 | imm19_12; - write32le(Loc, Insn); + write32le(loc, insn); return; } case R_RISCV_BRANCH: { - checkInt(Loc, static_cast(Val) >> 1, 12, Type); - checkAlignment(Loc, Val, 2, Type); + checkInt(loc, static_cast(val) >> 1, 12, type); + checkAlignment(loc, val, 2, type); - uint32_t Insn = read32le(Loc) & 0x1FFF07F; - uint32_t Imm12 = extractBits(Val, 12, 12) << 31; - uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25; - uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8; - uint32_t Imm11 = extractBits(Val, 11, 11) << 7; - Insn |= Imm12 | Imm10_5 | Imm4_1 | Imm11; + uint32_t insn = read32le(loc) & 0x1FFF07F; + uint32_t imm12 = extractBits(val, 12, 12) << 31; + uint32_t imm10_5 = extractBits(val, 10, 5) << 25; + uint32_t imm4_1 = extractBits(val, 4, 1) << 8; + uint32_t imm11 = extractBits(val, 11, 11) << 7; + insn |= imm12 | imm10_5 | imm4_1 | imm11; - write32le(Loc, Insn); + write32le(loc, insn); return; } // auipc + jalr pair case R_RISCV_CALL: case R_RISCV_CALL_PLT: { - int64_t Hi = SignExtend64(Val + 0x800, Bits) >> 12; - checkInt(Loc, Hi, 20, Type); - if (isInt<20>(Hi)) { - relocateOne(Loc, R_RISCV_PCREL_HI20, Val); - relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val); + int64_t hi = SignExtend64(val + 0x800, bits) >> 12; + checkInt(loc, hi, 20, type); + if (isInt<20>(hi)) { + relocateOne(loc, R_RISCV_PCREL_HI20, val); + relocateOne(loc + 4, R_RISCV_PCREL_LO12_I, val); } return; } @@ -341,78 +341,78 @@ case R_RISCV_TLS_GOT_HI20: case R_RISCV_TPREL_HI20: case R_RISCV_HI20: { - uint64_t Hi = Val + 0x800; - checkInt(Loc, SignExtend64(Hi, Bits) >> 12, 20, Type); - write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000)); + uint64_t hi = val + 0x800; + checkInt(loc, SignExtend64(hi, bits) >> 12, 20, type); + write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000)); return; } case R_RISCV_PCREL_LO12_I: case R_RISCV_TPREL_LO12_I: case R_RISCV_LO12_I: { - uint64_t Hi = (Val + 0x800) >> 12; - uint64_t Lo = Val - (Hi << 12); - write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20)); + uint64_t hi = (val + 0x800) >> 12; + uint64_t lo = val - (hi << 12); + write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20)); return; } case R_RISCV_PCREL_LO12_S: case R_RISCV_TPREL_LO12_S: case R_RISCV_LO12_S: { - uint64_t Hi = (Val + 0x800) >> 12; - uint64_t Lo = Val - (Hi << 12); - uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25; - uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7; - write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0); + uint64_t hi = (val + 0x800) >> 12; + uint64_t lo = val - (hi << 12); + uint32_t imm11_5 = extractBits(lo, 11, 5) << 25; + uint32_t imm4_0 = extractBits(lo, 4, 0) << 7; + write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0); return; } case R_RISCV_ADD8: - *Loc += Val; + *loc += val; return; case R_RISCV_ADD16: - write16le(Loc, read16le(Loc) + Val); + write16le(loc, read16le(loc) + val); return; case R_RISCV_ADD32: - write32le(Loc, read32le(Loc) + Val); + write32le(loc, read32le(loc) + val); return; case R_RISCV_ADD64: - write64le(Loc, read64le(Loc) + Val); + write64le(loc, read64le(loc) + val); return; case R_RISCV_SUB6: - *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f); + *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f); return; case R_RISCV_SUB8: - *Loc -= Val; + *loc -= val; return; case R_RISCV_SUB16: - write16le(Loc, read16le(Loc) - Val); + write16le(loc, read16le(loc) - val); return; case R_RISCV_SUB32: - write32le(Loc, read32le(Loc) - Val); + write32le(loc, read32le(loc) - val); return; case R_RISCV_SUB64: - write64le(Loc, read64le(Loc) - Val); + write64le(loc, read64le(loc) - val); return; case R_RISCV_SET6: - *Loc = (*Loc & 0xc0) | (Val & 0x3f); + *loc = (*loc & 0xc0) | (val & 0x3f); return; case R_RISCV_SET8: - *Loc = Val; + *loc = val; return; case R_RISCV_SET16: - write16le(Loc, Val); + write16le(loc, val); return; case R_RISCV_SET32: case R_RISCV_32_PCREL: - write32le(Loc, Val); + write32le(loc, val); return; case R_RISCV_TLS_DTPREL32: - write32le(Loc, Val - DTPOffset); + write32le(loc, val - dtpOffset); break; case R_RISCV_TLS_DTPREL64: - write64le(Loc, Val - DTPOffset); + write64le(loc, val - dtpOffset); break; case R_RISCV_ALIGN: @@ -430,13 +430,13 @@ case R_RISCV_GPREL_I: case R_RISCV_GPREL_S: default: - error(getErrorLocation(Loc) + - "unimplemented relocation: " + toString(Type)); + error(getErrorLocation(loc) + + "unimplemented relocation: " + toString(type)); return; } } TargetInfo *elf::getRISCVTargetInfo() { - static RISCV Target; - return &Target; + static RISCV target; + return ⌖ } Index: lld/trunk/ELF/Arch/SPARCV9.cpp =================================================================== --- lld/trunk/ELF/Arch/SPARCV9.cpp +++ lld/trunk/ELF/Arch/SPARCV9.cpp @@ -23,32 +23,32 @@ class SPARCV9 final : public TargetInfo { public: SPARCV9(); - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void writePlt(uint8_t *buf, uint64_t gotEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace SPARCV9::SPARCV9() { - CopyRel = R_SPARC_COPY; - GotRel = R_SPARC_GLOB_DAT; - NoneRel = R_SPARC_NONE; - PltRel = R_SPARC_JMP_SLOT; - RelativeRel = R_SPARC_RELATIVE; - SymbolicRel = R_SPARC_64; - PltEntrySize = 32; - PltHeaderSize = 4 * PltEntrySize; - - DefaultCommonPageSize = 8192; - DefaultMaxPageSize = 0x100000; - DefaultImageBase = 0x100000; + copyRel = R_SPARC_COPY; + gotRel = R_SPARC_GLOB_DAT; + noneRel = R_SPARC_NONE; + pltRel = R_SPARC_JMP_SLOT; + relativeRel = R_SPARC_RELATIVE; + symbolicRel = R_SPARC_64; + pltEntrySize = 32; + pltHeaderSize = 4 * pltEntrySize; + + defaultCommonPageSize = 8192; + defaultMaxPageSize = 0x100000; + defaultImageBase = 0x100000; } -RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - switch (Type) { +RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { case R_SPARC_32: case R_SPARC_UA32: case R_SPARC_64: @@ -68,65 +68,65 @@ case R_SPARC_NONE: return R_NONE; default: - error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + - ") against symbol " + toString(S)); + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); return R_NONE; } } -void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_SPARC_32: case R_SPARC_UA32: // V-word32 - checkUInt(Loc, Val, 32, Type); - write32be(Loc, Val); + checkUInt(loc, val, 32, type); + write32be(loc, val); break; case R_SPARC_DISP32: // V-disp32 - checkInt(Loc, Val, 32, Type); - write32be(Loc, Val); + checkInt(loc, val, 32, type); + write32be(loc, val); break; case R_SPARC_WDISP30: case R_SPARC_WPLT30: // V-disp30 - checkInt(Loc, Val, 32, Type); - write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff)); + checkInt(loc, val, 32, type); + write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); break; case R_SPARC_22: // V-imm22 - checkUInt(Loc, Val, 22, Type); - write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff)); + checkUInt(loc, val, 22, type); + write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); break; case R_SPARC_GOT22: case R_SPARC_PC22: // T-imm22 - write32be(Loc, (read32be(Loc) & ~0x003fffff) | ((Val >> 10) & 0x003fffff)); + write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); break; case R_SPARC_WDISP19: // V-disp19 - checkInt(Loc, Val, 21, Type); - write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff)); + checkInt(loc, val, 21, type); + write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); break; case R_SPARC_GOT10: case R_SPARC_PC10: // T-simm10 - write32be(Loc, (read32be(Loc) & ~0x000003ff) | (Val & 0x000003ff)); + write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); break; case R_SPARC_64: case R_SPARC_UA64: // V-xword64 - write64be(Loc, Val); + write64be(loc, val); break; default: llvm_unreachable("unknown relocation"); } } -void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t PltData[] = { +void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t pltData[] = { 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 0x01, 0x00, 0x00, 0x00, // nop @@ -136,14 +136,14 @@ 0x01, 0x00, 0x00, 0x00, // nop 0x01, 0x00, 0x00, 0x00 // nop }; - memcpy(Buf, PltData, sizeof(PltData)); + memcpy(buf, pltData, sizeof(pltData)); - uint64_t Off = PltHeaderSize + PltEntrySize * Index; - relocateOne(Buf, R_SPARC_22, Off); - relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize)); + uint64_t off = pltHeaderSize + pltEntrySize * index; + relocateOne(buf, R_SPARC_22, off); + relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); } TargetInfo *elf::getSPARCV9TargetInfo() { - static SPARCV9 Target; - return &Target; + static SPARCV9 target; + return ⌖ } Index: lld/trunk/ELF/Arch/X86.cpp =================================================================== --- lld/trunk/ELF/Arch/X86.cpp +++ lld/trunk/ELF/Arch/X86.cpp @@ -23,63 +23,63 @@ class X86 : public TargetInfo { public: X86(); - int getTlsGdRelaxSkip(RelType Type) const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override; - void writeGotPltHeader(uint8_t *Buf) const override; - RelType getDynRel(RelType Type) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; + int getTlsGdRelaxSkip(RelType type) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; + void writeGotPltHeader(uint8_t *buf) const override; + RelType getDynRel(RelType type) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writeIgotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override; }; } // namespace X86::X86() { - CopyRel = R_386_COPY; - GotRel = R_386_GLOB_DAT; - NoneRel = R_386_NONE; - PltRel = R_386_JUMP_SLOT; - IRelativeRel = R_386_IRELATIVE; - RelativeRel = R_386_RELATIVE; - SymbolicRel = R_386_32; - TlsGotRel = R_386_TLS_TPOFF; - TlsModuleIndexRel = R_386_TLS_DTPMOD32; - TlsOffsetRel = R_386_TLS_DTPOFF32; - PltEntrySize = 16; - PltHeaderSize = 16; - TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 + copyRel = R_386_COPY; + gotRel = R_386_GLOB_DAT; + noneRel = R_386_NONE; + pltRel = R_386_JUMP_SLOT; + iRelativeRel = R_386_IRELATIVE; + relativeRel = R_386_RELATIVE; + symbolicRel = R_386_32; + tlsGotRel = R_386_TLS_TPOFF; + tlsModuleIndexRel = R_386_TLS_DTPMOD32; + tlsOffsetRel = R_386_TLS_DTPOFF32; + pltEntrySize = 16; + pltHeaderSize = 16; + trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 // Align to the non-PAE large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. - DefaultImageBase = 0x400000; + defaultImageBase = 0x400000; } -int X86::getTlsGdRelaxSkip(RelType Type) const { +int X86::getTlsGdRelaxSkip(RelType type) const { return 2; } -RelExpr X86::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { +RelExpr X86::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { // There are 4 different TLS variable models with varying degrees of // flexibility and performance. LocalExec and InitialExec models are fast but // less-flexible models. If they are in use, we set DF_STATIC_TLS flag in the // dynamic section to let runtime know about that. - if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || Type == R_386_TLS_IE || - Type == R_386_TLS_GOTIE) - Config->HasStaticTlsModel = true; + if (type == R_386_TLS_LE || type == R_386_TLS_LE_32 || type == R_386_TLS_IE || + type == R_386_TLS_GOTIE) + config->hasStaticTlsModel = true; - switch (Type) { + switch (type) { case R_386_8: case R_386_16: case R_386_32: @@ -137,7 +137,7 @@ // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at // the byte, we can determine whether the instruction uses the operand as an // absolute address (R_GOT) or a register-relative address (R_GOTPLT). - return (Loc[-1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT; + return (loc[-1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT; case R_386_TLS_GOTIE: return R_GOTPLT; case R_386_GOTOFF: @@ -149,17 +149,17 @@ case R_386_NONE: return R_NONE; default: - error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + - ") against symbol " + toString(S)); + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); return R_NONE; } } -RelExpr X86::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - switch (Expr) { +RelExpr X86::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + switch (expr) { default: - return Expr; + return expr; case R_RELAX_TLS_GD_TO_IE: return R_RELAX_TLS_GD_TO_IE_GOTPLT; case R_RELAX_TLS_GD_TO_LE: @@ -167,84 +167,84 @@ } } -void X86::writeGotPltHeader(uint8_t *Buf) const { - write32le(Buf, Main->Dynamic->getVA()); +void X86::writeGotPltHeader(uint8_t *buf) const { + write32le(buf, mainPart->dynamic->getVA()); } -void X86::writeGotPlt(uint8_t *Buf, const Symbol &S) const { +void X86::writeGotPlt(uint8_t *buf, const Symbol &s) const { // Entries in .got.plt initially points back to the corresponding // PLT entries with a fixed offset to skip the first instruction. - write32le(Buf, S.getPltVA() + 6); + write32le(buf, s.getPltVA() + 6); } -void X86::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { +void X86::writeIgotPlt(uint8_t *buf, const Symbol &s) const { // An x86 entry is the address of the ifunc resolver function. - write32le(Buf, S.getVA()); + write32le(buf, s.getVA()); } -RelType X86::getDynRel(RelType Type) const { - if (Type == R_386_TLS_LE) +RelType X86::getDynRel(RelType type) const { + if (type == R_386_TLS_LE) return R_386_TLS_TPOFF; - if (Type == R_386_TLS_LE_32) + if (type == R_386_TLS_LE_32) return R_386_TLS_TPOFF32; - return Type; + return type; } -void X86::writePltHeader(uint8_t *Buf) const { - if (Config->Pic) { - const uint8_t V[] = { +void X86::writePltHeader(uint8_t *buf) const { + if (config->isPic) { + const uint8_t v[] = { 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx) 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx) 0x90, 0x90, 0x90, 0x90 // nop }; - memcpy(Buf, V, sizeof(V)); + memcpy(buf, v, sizeof(v)); return; } - const uint8_t PltData[] = { + const uint8_t pltData[] = { 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4) 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8) 0x90, 0x90, 0x90, 0x90, // nop }; - memcpy(Buf, PltData, sizeof(PltData)); - uint32_t GotPlt = In.GotPlt->getVA(); - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 8, GotPlt + 8); + memcpy(buf, pltData, sizeof(pltData)); + uint32_t gotPlt = in.gotPlt->getVA(); + write32le(buf + 2, gotPlt + 4); + write32le(buf + 8, gotPlt + 8); } -void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - if (Config->Pic) { - const uint8_t Inst[] = { +void X86::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + if (config->isPic) { + const uint8_t inst[] = { 0xff, 0xa3, 0, 0, 0, 0, // jmp *foo@GOT(%ebx) 0x68, 0, 0, 0, 0, // pushl $reloc_offset 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC }; - memcpy(Buf, Inst, sizeof(Inst)); - write32le(Buf + 2, GotPltEntryAddr - In.GotPlt->getVA()); + memcpy(buf, inst, sizeof(inst)); + write32le(buf + 2, gotPltEntryAddr - in.gotPlt->getVA()); } else { - const uint8_t Inst[] = { + const uint8_t inst[] = { 0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT 0x68, 0, 0, 0, 0, // pushl $reloc_offset 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC }; - memcpy(Buf, Inst, sizeof(Inst)); - write32le(Buf + 2, GotPltEntryAddr); + memcpy(buf, inst, sizeof(inst)); + write32le(buf + 2, gotPltEntryAddr); } - write32le(Buf + 7, RelOff); - write32le(Buf + 12, -PltHeaderSize - PltEntrySize * Index - 16); + write32le(buf + 7, relOff); + write32le(buf + 12, -pltHeaderSize - pltEntrySize * index - 16); } -int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const { - switch (Type) { +int64_t X86::getImplicitAddend(const uint8_t *buf, RelType type) const { + switch (type) { case R_386_8: case R_386_PC8: - return SignExtend64<8>(*Buf); + return SignExtend64<8>(*buf); case R_386_16: case R_386_PC16: - return SignExtend64<16>(read16le(Buf)); + return SignExtend64<16>(read16le(buf)); case R_386_32: case R_386_GOT32: case R_386_GOT32X: @@ -254,28 +254,28 @@ case R_386_PLT32: case R_386_TLS_LDO_32: case R_386_TLS_LE: - return SignExtend64<32>(read32le(Buf)); + return SignExtend64<32>(read32le(buf)); default: return 0; } } -void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_386_8: // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are // being used for some 16-bit programs such as boot loaders, so // we want to support them. - checkIntUInt(Loc, Val, 8, Type); - *Loc = Val; + checkIntUInt(loc, val, 8, type); + *loc = val; break; case R_386_PC8: - checkInt(Loc, Val, 8, Type); - *Loc = Val; + checkInt(loc, val, 8, type); + *loc = val; break; case R_386_16: - checkIntUInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16le(loc, val); break; case R_386_PC16: // R_386_PC16 is normally used with 16 bit code. In that situation @@ -288,8 +288,8 @@ // current location subtracted from it. // We just check that Val fits in 17 bits. This misses some cases, but // should have no false positives. - checkInt(Loc, Val, 17, Type); - write16le(Loc, Val); + checkInt(loc, val, 17, type); + write16le(loc, val); break; case R_386_32: case R_386_GOT32: @@ -310,86 +310,86 @@ case R_386_TLS_LE_32: case R_386_TLS_TPOFF: case R_386_TLS_TPOFF32: - checkInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkInt(loc, val, 32, type); + write32le(loc, val); break; default: llvm_unreachable("unknown relocation"); } } -void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { // Convert // leal x@tlsgd(, %ebx, 1), // call __tls_get_addr@plt // to // movl %gs:0,%eax // subl $x@ntpoff,%eax - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); - write32le(Loc + 5, Val); + memcpy(loc - 3, inst, sizeof(inst)); + write32le(loc + 5, val); } -void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { // Convert // leal x@tlsgd(, %ebx, 1), // call __tls_get_addr@plt // to // movl %gs:0, %eax // addl x@gotntpoff(%ebx), %eax - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax }; - memcpy(Loc - 3, Inst, sizeof(Inst)); - write32le(Loc + 5, Val); + memcpy(loc - 3, inst, sizeof(inst)); + write32le(loc + 5, val); } // In some conditions, relocations can be optimized to avoid using GOT. // This function does that for Initial Exec to Local Exec case. -void X86::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { +void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { // Ulrich's document section 6.2 says that @gotntpoff can // be used with MOVL or ADDL instructions. // @indntpoff is similar to @gotntpoff, but for use in // position dependent code. - uint8_t Reg = (Loc[-1] >> 3) & 7; + uint8_t reg = (loc[-1] >> 3) & 7; - if (Type == R_386_TLS_IE) { - if (Loc[-1] == 0xa1) { + if (type == R_386_TLS_IE) { + if (loc[-1] == 0xa1) { // "movl foo@indntpoff,%eax" -> "movl $foo,%eax" // This case is different from the generic case below because // this is a 5 byte instruction while below is 6 bytes. - Loc[-1] = 0xb8; - } else if (Loc[-2] == 0x8b) { + loc[-1] = 0xb8; + } else if (loc[-2] == 0x8b) { // "movl foo@indntpoff,%reg" -> "movl $foo,%reg" - Loc[-2] = 0xc7; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0xc7; + loc[-1] = 0xc0 | reg; } else { // "addl foo@indntpoff,%reg" -> "addl $foo,%reg" - Loc[-2] = 0x81; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0x81; + loc[-1] = 0xc0 | reg; } } else { - assert(Type == R_386_TLS_GOTIE); - if (Loc[-2] == 0x8b) { + assert(type == R_386_TLS_GOTIE); + if (loc[-2] == 0x8b) { // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg" - Loc[-2] = 0xc7; - Loc[-1] = 0xc0 | Reg; + loc[-2] = 0xc7; + loc[-1] = 0xc0 | reg; } else { // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg" - Loc[-2] = 0x8d; - Loc[-1] = 0x80 | (Reg << 3) | Reg; + loc[-2] = 0x8d; + loc[-1] = 0x80 | (reg << 3) | reg; } } - write32le(Loc, Val); + write32le(loc, val); } -void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - if (Type == R_386_TLS_LDO_32) { - write32le(Loc, Val); +void X86::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { + if (type == R_386_TLS_LDO_32) { + write32le(loc, val); return; } @@ -400,45 +400,45 @@ // movl %gs:0,%eax // nop // leal 0(%esi,1),%esi - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax 0x90, // nop 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi }; - memcpy(Loc - 2, Inst, sizeof(Inst)); + memcpy(loc - 2, inst, sizeof(inst)); } namespace { class RetpolinePic : public X86 { public: RetpolinePic(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; class RetpolineNoPic : public X86 { public: RetpolineNoPic(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; } // namespace RetpolinePic::RetpolinePic() { - PltHeaderSize = 48; - PltEntrySize = 32; + pltHeaderSize = 48; + pltEntrySize = 32; } -void RetpolinePic::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - write32le(Buf, S.getPltVA() + 17); +void RetpolinePic::writeGotPlt(uint8_t *buf, const Symbol &s) const { + write32le(buf, s.getPltVA() + 17); } -void RetpolinePic::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { +void RetpolinePic::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { 0xff, 0xb3, 4, 0, 0, 0, // 0: pushl 4(%ebx) 0x50, // 6: pushl %eax 0x8b, 0x83, 8, 0, 0, 0, // 7: mov 8(%ebx), %eax @@ -455,13 +455,13 @@ 0xc3, // 2e: ret 0xcc, // 2f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); } -void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void RetpolinePic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x50, // pushl %eax 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax 0xe8, 0, 0, 0, 0, // call plt+0x20 @@ -470,28 +470,28 @@ 0xe9, 0, 0, 0, 0, // jmp plt+0 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - uint32_t Ebx = In.GotPlt->getVA(); - unsigned Off = PltHeaderSize + PltEntrySize * Index; - write32le(Buf + 3, GotPltEntryAddr - Ebx); - write32le(Buf + 8, -Off - 12 + 32); - write32le(Buf + 13, -Off - 17 + 18); - write32le(Buf + 18, RelOff); - write32le(Buf + 23, -Off - 27); + uint32_t ebx = in.gotPlt->getVA(); + unsigned off = pltHeaderSize + pltEntrySize * index; + write32le(buf + 3, gotPltEntryAddr - ebx); + write32le(buf + 8, -off - 12 + 32); + write32le(buf + 13, -off - 17 + 18); + write32le(buf + 18, relOff); + write32le(buf + 23, -off - 27); } RetpolineNoPic::RetpolineNoPic() { - PltHeaderSize = 48; - PltEntrySize = 32; + pltHeaderSize = 48; + pltEntrySize = 32; } -void RetpolineNoPic::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - write32le(Buf, S.getPltVA() + 16); +void RetpolineNoPic::writeGotPlt(uint8_t *buf, const Symbol &s) const { + write32le(buf, s.getPltVA() + 16); } -void RetpolineNoPic::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { +void RetpolineNoPic::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { 0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4 0x50, // 6: pushl %eax 0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax @@ -509,17 +509,17 @@ 0xc3, // 2e: ret 0xcc, // 2f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - uint32_t GotPlt = In.GotPlt->getVA(); - write32le(Buf + 2, GotPlt + 4); - write32le(Buf + 8, GotPlt + 8); + uint32_t gotPlt = in.gotPlt->getVA(); + write32le(buf + 2, gotPlt + 4); + write32le(buf + 8, gotPlt + 8); } -void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void RetpolineNoPic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x50, // 0: pushl %eax 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax 0xe8, 0, 0, 0, 0, // 6: call plt+0x20 @@ -529,26 +529,26 @@ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding 0xcc, // 1f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - unsigned Off = PltHeaderSize + PltEntrySize * Index; - write32le(Buf + 2, GotPltEntryAddr); - write32le(Buf + 7, -Off - 11 + 32); - write32le(Buf + 12, -Off - 16 + 17); - write32le(Buf + 17, RelOff); - write32le(Buf + 22, -Off - 26); + unsigned off = pltHeaderSize + pltEntrySize * index; + write32le(buf + 2, gotPltEntryAddr); + write32le(buf + 7, -off - 11 + 32); + write32le(buf + 12, -off - 16 + 17); + write32le(buf + 17, relOff); + write32le(buf + 22, -off - 26); } TargetInfo *elf::getX86TargetInfo() { - if (Config->ZRetpolineplt) { - if (Config->Pic) { - static RetpolinePic T; - return &T; + if (config->zRetpolineplt) { + if (config->isPic) { + static RetpolinePic t; + return &t; } - static RetpolineNoPic T; - return &T; + static RetpolineNoPic t; + return &t; } - static X86 T; - return &T; + static X86 t; + return &t; } Index: lld/trunk/ELF/Arch/X86_64.cpp =================================================================== --- lld/trunk/ELF/Arch/X86_64.cpp +++ lld/trunk/ELF/Arch/X86_64.cpp @@ -25,58 +25,58 @@ class X86_64 : public TargetInfo { public: X86_64(); - int getTlsGdRelaxSkip(RelType Type) const override; - RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const override; - RelType getDynRel(RelType Type) const override; - void writeGotPltHeader(uint8_t *Buf) const override; - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; - void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; - - RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const override; - void relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; - bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const override; + int getTlsGdRelaxSkip(RelType type) const override; + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + RelType getDynRel(RelType type) const override; + void writeGotPltHeader(uint8_t *buf) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + + RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const override; + void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override; + void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override; + bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const override; }; } // namespace X86_64::X86_64() { - CopyRel = R_X86_64_COPY; - GotRel = R_X86_64_GLOB_DAT; - NoneRel = R_X86_64_NONE; - PltRel = R_X86_64_JUMP_SLOT; - RelativeRel = R_X86_64_RELATIVE; - IRelativeRel = R_X86_64_IRELATIVE; - SymbolicRel = R_X86_64_64; - TlsDescRel = R_X86_64_TLSDESC; - TlsGotRel = R_X86_64_TPOFF64; - TlsModuleIndexRel = R_X86_64_DTPMOD64; - TlsOffsetRel = R_X86_64_DTPOFF64; - PltEntrySize = 16; - PltHeaderSize = 16; - TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 + copyRel = R_X86_64_COPY; + gotRel = R_X86_64_GLOB_DAT; + noneRel = R_X86_64_NONE; + pltRel = R_X86_64_JUMP_SLOT; + relativeRel = R_X86_64_RELATIVE; + iRelativeRel = R_X86_64_IRELATIVE; + symbolicRel = R_X86_64_64; + tlsDescRel = R_X86_64_TLSDESC; + tlsGotRel = R_X86_64_TPOFF64; + tlsModuleIndexRel = R_X86_64_DTPMOD64; + tlsOffsetRel = R_X86_64_DTPOFF64; + pltEntrySize = 16; + pltHeaderSize = 16; + trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 // Align to the large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. - DefaultImageBase = 0x200000; + defaultImageBase = 0x200000; } -int X86_64::getTlsGdRelaxSkip(RelType Type) const { return 2; } +int X86_64::getTlsGdRelaxSkip(RelType type) const { return 2; } -RelExpr X86_64::getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const { - if (Type == R_X86_64_GOTTPOFF) - Config->HasStaticTlsModel = true; +RelExpr X86_64::getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const { + if (type == R_X86_64_GOTTPOFF) + config->hasStaticTlsModel = true; - switch (Type) { + switch (type) { case R_X86_64_8: case R_X86_64_16: case R_X86_64_32: @@ -122,62 +122,62 @@ case R_X86_64_NONE: return R_NONE; default: - error(getErrorLocation(Loc) + "unknown relocation (" + Twine(Type) + - ") against symbol " + toString(S)); + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); return R_NONE; } } -void X86_64::writeGotPltHeader(uint8_t *Buf) const { +void X86_64::writeGotPltHeader(uint8_t *buf) const { // The first entry holds the value of _DYNAMIC. It is not clear why that is // required, but it is documented in the psabi and the glibc dynamic linker // seems to use it (note that this is relevant for linking ld.so, not any // other program). - write64le(Buf, Main->Dynamic->getVA()); + write64le(buf, mainPart->dynamic->getVA()); } -void X86_64::writeGotPlt(uint8_t *Buf, const Symbol &S) const { +void X86_64::writeGotPlt(uint8_t *buf, const Symbol &s) const { // See comments in X86::writeGotPlt. - write64le(Buf, S.getPltVA() + 6); + write64le(buf, s.getPltVA() + 6); } -void X86_64::writePltHeader(uint8_t *Buf) const { - const uint8_t PltData[] = { +void X86_64::writePltHeader(uint8_t *buf) const { + const uint8_t pltData[] = { 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip) 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip) 0x0f, 0x1f, 0x40, 0x00, // nop }; - memcpy(Buf, PltData, sizeof(PltData)); - uint64_t GotPlt = In.GotPlt->getVA(); - uint64_t Plt = In.Plt->getVA(); - write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8 - write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16 + memcpy(buf, pltData, sizeof(pltData)); + uint64_t gotPlt = in.gotPlt->getVA(); + uint64_t plt = in.plt->getVA(); + write32le(buf + 2, gotPlt - plt + 2); // GOTPLT+8 + write32le(buf + 8, gotPlt - plt + 4); // GOTPLT+16 } -void X86_64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Inst[] = { +void X86_64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t inst[] = { 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip) 0x68, 0, 0, 0, 0, // pushq 0xe9, 0, 0, 0, 0, // jmpq plt[0] }; - memcpy(Buf, Inst, sizeof(Inst)); + memcpy(buf, inst, sizeof(inst)); - write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6); - write32le(Buf + 7, Index); - write32le(Buf + 12, -PltHeaderSize - PltEntrySize * Index - 16); + write32le(buf + 2, gotPltEntryAddr - pltEntryAddr - 6); + write32le(buf + 7, index); + write32le(buf + 12, -pltHeaderSize - pltEntrySize * index - 16); } -RelType X86_64::getDynRel(RelType Type) const { - if (Type == R_X86_64_64 || Type == R_X86_64_PC64 || Type == R_X86_64_SIZE32 || - Type == R_X86_64_SIZE64) - return Type; +RelType X86_64::getDynRel(RelType type) const { + if (type == R_X86_64_64 || type == R_X86_64_PC64 || type == R_X86_64_SIZE32 || + type == R_X86_64_SIZE64) + return type; return R_X86_64_NONE; } -void X86_64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - if (Type == R_X86_64_TLSGD) { +void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const { + if (type == R_X86_64_TLSGD) { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -185,39 +185,39 @@ // rex64 // call __tls_get_addr@plt // to the following two instructions. - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax }; - memcpy(Loc - 4, Inst, sizeof(Inst)); + memcpy(loc - 4, inst, sizeof(inst)); // The original code used a pc relative relocation and so we have to // compensate for the -4 in had in the addend. - write32le(Loc + 8, Val + 4); + write32le(loc + 8, val + 4); } else { // Convert // lea x@tlsgd(%rip), %rax // call *(%rax) // to the following two instructions. - assert(Type == R_X86_64_GOTPC32_TLSDESC); - if (memcmp(Loc - 3, "\x48\x8d\x05", 3)) { - error(getErrorLocation(Loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used " + assert(type == R_X86_64_GOTPC32_TLSDESC); + if (memcmp(loc - 3, "\x48\x8d\x05", 3)) { + error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used " "in callq *x@tlsdesc(%rip), %rax"); return; } // movq $x@tpoff(%rip),%rax - Loc[-2] = 0xc7; - Loc[-1] = 0xc0; - write32le(Loc, Val + 4); + loc[-2] = 0xc7; + loc[-1] = 0xc0; + write32le(loc, val + 4); // xchg ax,ax - Loc[4] = 0x66; - Loc[5] = 0x90; + loc[4] = 0x66; + loc[5] = 0x90; } } -void X86_64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { - if (Type == R_X86_64_TLSGD) { +void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { + if (type == R_X86_64_TLSGD) { // Convert // .byte 0x66 // leaq x@tlsgd(%rip), %rdi @@ -225,96 +225,96 @@ // rex64 // call __tls_get_addr@plt // to the following two instructions. - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@gottpoff(%rip),%rax }; - memcpy(Loc - 4, Inst, sizeof(Inst)); + memcpy(loc - 4, inst, sizeof(inst)); // Both code sequences are PC relatives, but since we are moving the // constant forward by 8 bytes we have to subtract the value by 8. - write32le(Loc + 8, Val - 8); + write32le(loc + 8, val - 8); } else { // Convert // lea x@tlsgd(%rip), %rax // call *(%rax) // to the following two instructions. - assert(Type == R_X86_64_GOTPC32_TLSDESC); - if (memcmp(Loc - 3, "\x48\x8d\x05", 3)) { - error(getErrorLocation(Loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used " + assert(type == R_X86_64_GOTPC32_TLSDESC); + if (memcmp(loc - 3, "\x48\x8d\x05", 3)) { + error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used " "in callq *x@tlsdesc(%rip), %rax"); return; } // movq x@gottpoff(%rip),%rax - Loc[-2] = 0x8b; - write32le(Loc, Val); + loc[-2] = 0x8b; + write32le(loc, val); // xchg ax,ax - Loc[4] = 0x66; - Loc[5] = 0x90; + loc[4] = 0x66; + loc[5] = 0x90; } } // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to // R_X86_64_TPOFF32 so that it does not use GOT. -void X86_64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - uint8_t *Inst = Loc - 3; - uint8_t Reg = Loc[-1] >> 3; - uint8_t *RegSlot = Loc - 1; +void X86_64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { + uint8_t *inst = loc - 3; + uint8_t reg = loc[-1] >> 3; + uint8_t *regSlot = loc - 1; // Note that ADD with RSP or R12 is converted to ADD instead of LEA // because LEA with these registers needs 4 bytes to encode and thus // wouldn't fit the space. - if (memcmp(Inst, "\x48\x03\x25", 3) == 0) { + if (memcmp(inst, "\x48\x03\x25", 3) == 0) { // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp" - memcpy(Inst, "\x48\x81\xc4", 3); - } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) { + memcpy(inst, "\x48\x81\xc4", 3); + } else if (memcmp(inst, "\x4c\x03\x25", 3) == 0) { // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12" - memcpy(Inst, "\x49\x81\xc4", 3); - } else if (memcmp(Inst, "\x4c\x03", 2) == 0) { + memcpy(inst, "\x49\x81\xc4", 3); + } else if (memcmp(inst, "\x4c\x03", 2) == 0) { // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]" - memcpy(Inst, "\x4d\x8d", 2); - *RegSlot = 0x80 | (Reg << 3) | Reg; - } else if (memcmp(Inst, "\x48\x03", 2) == 0) { + memcpy(inst, "\x4d\x8d", 2); + *regSlot = 0x80 | (reg << 3) | reg; + } else if (memcmp(inst, "\x48\x03", 2) == 0) { // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg" - memcpy(Inst, "\x48\x8d", 2); - *RegSlot = 0x80 | (Reg << 3) | Reg; - } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) { + memcpy(inst, "\x48\x8d", 2); + *regSlot = 0x80 | (reg << 3) | reg; + } else if (memcmp(inst, "\x4c\x8b", 2) == 0) { // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]" - memcpy(Inst, "\x49\xc7", 2); - *RegSlot = 0xc0 | Reg; - } else if (memcmp(Inst, "\x48\x8b", 2) == 0) { + memcpy(inst, "\x49\xc7", 2); + *regSlot = 0xc0 | reg; + } else if (memcmp(inst, "\x48\x8b", 2) == 0) { // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg" - memcpy(Inst, "\x48\xc7", 2); - *RegSlot = 0xc0 | Reg; + memcpy(inst, "\x48\xc7", 2); + *regSlot = 0xc0 | reg; } else { - error(getErrorLocation(Loc - 3) + + error(getErrorLocation(loc - 3) + "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only"); } // The original code used a PC relative relocation. // Need to compensate for the -4 it had in the addend. - write32le(Loc, Val + 4); + write32le(loc, val + 4); } -void X86_64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { - if (Type == R_X86_64_DTPOFF64) { - write64le(Loc, Val); +void X86_64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const { + if (type == R_X86_64_DTPOFF64) { + write64le(loc, val); return; } - if (Type == R_X86_64_DTPOFF32) { - write32le(Loc, Val); + if (type == R_X86_64_DTPOFF32) { + write32le(loc, val); return; } - const uint8_t Inst[] = { + const uint8_t inst[] = { 0x66, 0x66, // .word 0x6666 0x66, // .byte 0x66 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax }; - if (Loc[4] == 0xe8) { + if (loc[4] == 0xe8) { // Convert // leaq bar@tlsld(%rip), %rdi # 48 8d 3d // callq __tls_get_addr@PLT # e8 @@ -324,11 +324,11 @@ // .byte 0x66 // mov %fs:0,%rax // leaq bar@tpoff(%rax), %rcx - memcpy(Loc - 3, Inst, sizeof(Inst)); + memcpy(loc - 3, inst, sizeof(inst)); return; } - if (Loc[4] == 0xff && Loc[5] == 0x15) { + if (loc[4] == 0xff && loc[5] == 0x15) { // Convert // leaq x@tlsld(%rip),%rdi # 48 8d 3d // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 @@ -337,36 +337,36 @@ // movq %fs:0,%rax // See "Table 11.9: LD -> LE Code Transition (LP64)" in // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf - Loc[-3] = 0x66; - memcpy(Loc - 2, Inst, sizeof(Inst)); + loc[-3] = 0x66; + memcpy(loc - 2, inst, sizeof(inst)); return; } - error(getErrorLocation(Loc - 3) + + error(getErrorLocation(loc - 3) + "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); } -void X86_64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { - switch (Type) { +void X86_64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { + switch (type) { case R_X86_64_8: - checkIntUInt(Loc, Val, 8, Type); - *Loc = Val; + checkIntUInt(loc, val, 8, type); + *loc = val; break; case R_X86_64_PC8: - checkInt(Loc, Val, 8, Type); - *Loc = Val; + checkInt(loc, val, 8, type); + *loc = val; break; case R_X86_64_16: - checkIntUInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkIntUInt(loc, val, 16, type); + write16le(loc, val); break; case R_X86_64_PC16: - checkInt(Loc, Val, 16, Type); - write16le(Loc, Val); + checkInt(loc, val, 16, type); + write16le(loc, val); break; case R_X86_64_32: - checkUInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkUInt(loc, val, 32, type); + write32le(loc, val); break; case R_X86_64_32S: case R_X86_64_TPOFF32: @@ -383,8 +383,8 @@ case R_X86_64_TLSLD: case R_X86_64_DTPOFF32: case R_X86_64_SIZE32: - checkInt(Loc, Val, 32, Type); - write32le(Loc, Val); + checkInt(loc, val, 32, type); + write32le(loc, val); break; case R_X86_64_64: case R_X86_64_DTPOFF64: @@ -393,37 +393,37 @@ case R_X86_64_GOT64: case R_X86_64_GOTOFF64: case R_X86_64_GOTPC64: - write64le(Loc, Val); + write64le(loc, val); break; default: llvm_unreachable("unknown relocation"); } } -RelExpr X86_64::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr RelExpr) const { - if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX) - return RelExpr; - const uint8_t Op = Data[-2]; - const uint8_t ModRm = Data[-1]; +RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr relExpr) const { + if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX) + return relExpr; + const uint8_t op = data[-2]; + const uint8_t modRm = data[-1]; // FIXME: When PIC is disabled and foo is defined locally in the // lower 32 bit address space, memory operand in mov can be converted into // immediate operand. Otherwise, mov must be changed to lea. We support only // latter relaxation at this moment. - if (Op == 0x8b) + if (op == 0x8b) return R_RELAX_GOT_PC; // Relax call and jmp. - if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25)) + if (op == 0xff && (modRm == 0x15 || modRm == 0x25)) return R_RELAX_GOT_PC; // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor. // If PIC then no relaxation is available. // We also don't relax test/binop instructions without REX byte, // they are 32bit operations and not common to have. - assert(Type == R_X86_64_REX_GOTPCRELX); - return Config->Pic ? RelExpr : R_RELAX_GOT_PC_NOPIC; + assert(type == R_X86_64_REX_GOTPCRELX); + return config->isPic ? relExpr : R_RELAX_GOT_PC_NOPIC; } // A subset of relaxations can only be applied for no-PIC. This method @@ -431,11 +431,11 @@ // "Intel 64 and IA-32 Architectures Software Developer's Manual V2" // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/ // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf) -static void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, - uint8_t ModRm) { - const uint8_t Rex = Loc[-3]; +static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op, + uint8_t modRm) { + const uint8_t rex = loc[-3]; // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg". - if (Op == 0x85) { + if (op == 0x85) { // See "TEST-Logical Compare" (4-428 Vol. 2B), // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension). @@ -452,11 +452,11 @@ // 0x38 == 00 111 000 binary. // We transfer reg2 to reg1 here as operand. // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3). - Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte. + loc[-1] = 0xc0 | (modRm & 0x38) >> 3; // ModR/M byte. // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32 // See "TEST-Logical Compare" (4-428 Vol. 2B). - Loc[-2] = 0xf7; + loc[-2] = 0xf7; // Move R bit to the B bit in REX byte. // REX byte is encoded as 0100WRXB, where @@ -469,8 +469,8 @@ // REX.B This 1-bit value is an extension to the MODRM.rm field or the // SIB.base field. // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A). - Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; - write32le(Loc, Val); + loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; + write32le(loc, val); return; } @@ -480,7 +480,7 @@ // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg". // Logic is close to one for test instruction above, but we also // write opcode extension here, see below for details. - Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte. + loc[-1] = 0xc0 | (modRm & 0x38) >> 3 | (op & 0x3c); // ModR/M byte. // Primary opcode is 0x81, opcode extension is one of: // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB, @@ -489,67 +489,67 @@ // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15), // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for // descriptions about each operation. - Loc[-2] = 0x81; - Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2; - write32le(Loc, Val); + loc[-2] = 0x81; + loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2; + write32le(loc, val); } -void X86_64::relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const { - const uint8_t Op = Loc[-2]; - const uint8_t ModRm = Loc[-1]; +void X86_64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const { + const uint8_t op = loc[-2]; + const uint8_t modRm = loc[-1]; // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg". - if (Op == 0x8b) { - Loc[-2] = 0x8d; - write32le(Loc, Val); + if (op == 0x8b) { + loc[-2] = 0x8d; + write32le(loc, val); return; } - if (Op != 0xff) { + if (op != 0xff) { // We are relaxing a rip relative to an absolute, so compensate // for the old -4 addend. - assert(!Config->Pic); - relaxGotNoPic(Loc, Val + 4, Op, ModRm); + assert(!config->isPic); + relaxGotNoPic(loc, val + 4, op, modRm); return; } // Convert call/jmp instructions. - if (ModRm == 0x15) { + if (modRm == 0x15) { // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo". // Instead we convert to "addr32 call foo" where addr32 is an instruction // prefix. That makes result expression to be a single instruction. - Loc[-2] = 0x67; // addr32 prefix - Loc[-1] = 0xe8; // call - write32le(Loc, Val); + loc[-2] = 0x67; // addr32 prefix + loc[-1] = 0xe8; // call + write32le(loc, val); return; } // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop". // jmp doesn't return, so it is fine to use nop here, it is just a stub. - assert(ModRm == 0x25); - Loc[-2] = 0xe9; // jmp - Loc[3] = 0x90; // nop - write32le(Loc - 1, Val + 1); + assert(modRm == 0x25); + loc[-2] = 0xe9; // jmp + loc[3] = 0x90; // nop + write32le(loc - 1, val + 1); } // A split-stack prologue starts by checking the amount of stack remaining // in one of two ways: // A) Comparing of the stack pointer to a field in the tcb. // B) Or a load of a stack pointer offset with an lea to r10 or r11. -bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const { - if (!Config->Is64) { +bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const { + if (!config->is64) { error("Target doesn't support split stacks."); return false; } - if (Loc + 8 >= End) + if (loc + 8 >= end) return false; // Replace "cmp %fs:0x70,%rsp" and subsequent branch // with "stc, nopl 0x0(%rax,%rax,1)" - if (memcmp(Loc, "\x64\x48\x3b\x24\x25", 5) == 0) { - memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8); + if (memcmp(loc, "\x64\x48\x3b\x24\x25", 5) == 0) { + memcpy(loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8); return true; } @@ -557,11 +557,11 @@ // be r10 or r11. The lea instruction feeds a subsequent compare which checks // if there is X available stack space. Making X larger effectively reserves // that much additional space. The stack grows downward so subtract the value. - if (memcmp(Loc, "\x4c\x8d\x94\x24", 4) == 0 || - memcmp(Loc, "\x4c\x8d\x9c\x24", 4) == 0) { + if (memcmp(loc, "\x4c\x8d\x94\x24", 4) == 0 || + memcmp(loc, "\x4c\x8d\x9c\x24", 4) == 0) { // The offset bytes are encoded four bytes after the start of the // instruction. - write32le(Loc + 4, read32le(Loc + 4) - 0x4000); + write32le(loc + 4, read32le(loc + 4) - 0x4000); return true; } return false; @@ -580,33 +580,33 @@ class Retpoline : public X86_64 { public: Retpoline(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override; - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override; + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; class RetpolineZNow : public X86_64 { public: RetpolineZNow(); - void writeGotPlt(uint8_t *Buf, const Symbol &S) const override {} - void writePltHeader(uint8_t *Buf) const override; - void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, - int32_t Index, unsigned RelOff) const override; + void writeGotPlt(uint8_t *buf, const Symbol &s) const override {} + void writePltHeader(uint8_t *buf) const override; + void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, + int32_t index, unsigned relOff) const override; }; } // namespace Retpoline::Retpoline() { - PltHeaderSize = 48; - PltEntrySize = 32; + pltHeaderSize = 48; + pltEntrySize = 32; } -void Retpoline::writeGotPlt(uint8_t *Buf, const Symbol &S) const { - write64le(Buf, S.getPltVA() + 17); +void Retpoline::writeGotPlt(uint8_t *buf, const Symbol &s) const { + write64le(buf, s.getPltVA() + 17); } -void Retpoline::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { +void Retpoline::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { 0xff, 0x35, 0, 0, 0, 0, // 0: pushq GOTPLT+8(%rip) 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 6: mov GOTPLT+16(%rip), %r11 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: callq next @@ -619,18 +619,18 @@ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - uint64_t GotPlt = In.GotPlt->getVA(); - uint64_t Plt = In.Plt->getVA(); - write32le(Buf + 2, GotPlt - Plt - 6 + 8); - write32le(Buf + 9, GotPlt - Plt - 13 + 16); + uint64_t gotPlt = in.gotPlt->getVA(); + uint64_t plt = in.plt->getVA(); + write32le(buf + 2, gotPlt - plt - 6 + 8); + write32le(buf + 9, gotPlt - plt - 13 + 16); } -void Retpoline::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void Retpoline::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0: mov foo@GOTPLT(%rip), %r11 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12 @@ -638,24 +638,24 @@ 0xe9, 0, 0, 0, 0, // 16: jmp plt+0 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - uint64_t Off = PltHeaderSize + PltEntrySize * Index; + uint64_t off = pltHeaderSize + pltEntrySize * index; - write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); - write32le(Buf + 8, -Off - 12 + 32); - write32le(Buf + 13, -Off - 17 + 18); - write32le(Buf + 18, Index); - write32le(Buf + 23, -Off - 27); + write32le(buf + 3, gotPltEntryAddr - pltEntryAddr - 7); + write32le(buf + 8, -off - 12 + 32); + write32le(buf + 13, -off - 17 + 18); + write32le(buf + 18, index); + write32le(buf + 23, -off - 27); } RetpolineZNow::RetpolineZNow() { - PltHeaderSize = 32; - PltEntrySize = 16; + pltHeaderSize = 32; + pltEntrySize = 16; } -void RetpolineZNow::writePltHeader(uint8_t *Buf) const { - const uint8_t Insn[] = { +void RetpolineZNow::writePltHeader(uint8_t *buf) const { + const uint8_t insn[] = { 0xe8, 0x0b, 0x00, 0x00, 0x00, // 0: call next 0xf3, 0x90, // 5: loop: pause 0x0f, 0xae, 0xe8, // 7: lfence @@ -667,35 +667,35 @@ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding 0xcc, // 1f: int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); } -void RetpolineZNow::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const { - const uint8_t Insn[] = { +void RetpolineZNow::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const { + const uint8_t insn[] = { 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11 0xe9, 0, 0, 0, 0, // jmp plt+0 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding }; - memcpy(Buf, Insn, sizeof(Insn)); + memcpy(buf, insn, sizeof(insn)); - write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); - write32le(Buf + 8, -PltHeaderSize - PltEntrySize * Index - 12); + write32le(buf + 3, gotPltEntryAddr - pltEntryAddr - 7); + write32le(buf + 8, -pltHeaderSize - pltEntrySize * index - 12); } static TargetInfo *getTargetInfo() { - if (Config->ZRetpolineplt) { - if (Config->ZNow) { - static RetpolineZNow T; - return &T; + if (config->zRetpolineplt) { + if (config->zNow) { + static RetpolineZNow t; + return &t; } - static Retpoline T; - return &T; + static Retpoline t; + return &t; } - static X86_64 T; - return &T; + static X86_64 t; + return &t; } TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo(); } Index: lld/trunk/ELF/CallGraphSort.cpp =================================================================== --- lld/trunk/ELF/CallGraphSort.cpp +++ lld/trunk/ELF/CallGraphSort.cpp @@ -51,24 +51,24 @@ namespace { struct Edge { - int From; - uint64_t Weight; + int from; + uint64_t weight; }; struct Cluster { - Cluster(int Sec, size_t S) : Sections{Sec}, Size(S) {} + Cluster(int sec, size_t s) : sections{sec}, size(s) {} double getDensity() const { - if (Size == 0) + if (size == 0) return 0; - return double(Weight) / double(Size); + return double(weight) / double(size); } - std::vector Sections; - size_t Size = 0; - uint64_t Weight = 0; - uint64_t InitialWeight = 0; - Edge BestPred = {-1, 0}; + std::vector sections; + size_t size = 0; + uint64_t weight = 0; + uint64_t initialWeight = 0; + Edge bestPred = {-1, 0}; }; class CallGraphSort { @@ -78,8 +78,8 @@ DenseMap run(); private: - std::vector Clusters; - std::vector Sections; + std::vector clusters; + std::vector sections; void groupClusters(); }; @@ -99,23 +99,23 @@ // Symbols, and generate a graph between InputSections with the provided // weights. CallGraphSort::CallGraphSort() { - MapVector &Profile = Config->CallGraphProfile; - DenseMap SecToCluster; + MapVector &profile = config->callGraphProfile; + DenseMap secToCluster; - auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int { - auto Res = SecToCluster.insert(std::make_pair(IS, Clusters.size())); - if (Res.second) { - Sections.push_back(IS); - Clusters.emplace_back(Clusters.size(), IS->getSize()); + auto getOrCreateNode = [&](const InputSectionBase *isec) -> int { + auto res = secToCluster.insert(std::make_pair(isec, clusters.size())); + if (res.second) { + sections.push_back(isec); + clusters.emplace_back(clusters.size(), isec->getSize()); } - return Res.first->second; + return res.first->second; }; // Create the graph. - for (std::pair &C : Profile) { - const auto *FromSB = cast(C.first.first->Repl); - const auto *ToSB = cast(C.first.second->Repl); - uint64_t Weight = C.second; + for (std::pair &c : profile) { + const auto *fromSB = cast(c.first.first->repl); + const auto *toSB = cast(c.first.second->repl); + uint64_t weight = c.second; // Ignore edges between input sections belonging to different output // sections. This is done because otherwise we would end up with clusters @@ -123,94 +123,94 @@ // output. This messes with the cluster size and density calculations. We // would also end up moving input sections in other output sections without // moving them closer to what calls them. - if (FromSB->getOutputSection() != ToSB->getOutputSection()) + if (fromSB->getOutputSection() != toSB->getOutputSection()) continue; - int From = GetOrCreateNode(FromSB); - int To = GetOrCreateNode(ToSB); + int from = getOrCreateNode(fromSB); + int to = getOrCreateNode(toSB); - Clusters[To].Weight += Weight; + clusters[to].weight += weight; - if (From == To) + if (from == to) continue; // Remember the best edge. - Cluster &ToC = Clusters[To]; - if (ToC.BestPred.From == -1 || ToC.BestPred.Weight < Weight) { - ToC.BestPred.From = From; - ToC.BestPred.Weight = Weight; + Cluster &toC = clusters[to]; + if (toC.bestPred.from == -1 || toC.bestPred.weight < weight) { + toC.bestPred.from = from; + toC.bestPred.weight = weight; } } - for (Cluster &C : Clusters) - C.InitialWeight = C.Weight; + for (Cluster &c : clusters) + c.initialWeight = c.weight; } // It's bad to merge clusters which would degrade the density too much. -static bool isNewDensityBad(Cluster &A, Cluster &B) { - double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size); - return NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION; +static bool isNewDensityBad(Cluster &a, Cluster &b) { + double newDensity = double(a.weight + b.weight) / double(a.size + b.size); + return newDensity < a.getDensity() / MAX_DENSITY_DEGRADATION; } -static void mergeClusters(Cluster &Into, Cluster &From) { - Into.Sections.insert(Into.Sections.end(), From.Sections.begin(), - From.Sections.end()); - Into.Size += From.Size; - Into.Weight += From.Weight; - From.Sections.clear(); - From.Size = 0; - From.Weight = 0; +static void mergeClusters(Cluster &into, Cluster &from) { + into.sections.insert(into.sections.end(), from.sections.begin(), + from.sections.end()); + into.size += from.size; + into.weight += from.weight; + from.sections.clear(); + from.size = 0; + from.weight = 0; } // Group InputSections into clusters using the Call-Chain Clustering heuristic // then sort the clusters by density. void CallGraphSort::groupClusters() { - std::vector SortedSecs(Clusters.size()); - std::vector SecToCluster(Clusters.size()); + std::vector sortedSecs(clusters.size()); + std::vector secToCluster(clusters.size()); - for (size_t I = 0; I < Clusters.size(); ++I) { - SortedSecs[I] = I; - SecToCluster[I] = &Clusters[I]; + for (size_t i = 0; i < clusters.size(); ++i) { + sortedSecs[i] = i; + secToCluster[i] = &clusters[i]; } - llvm::stable_sort(SortedSecs, [&](int A, int B) { - return Clusters[A].getDensity() > Clusters[B].getDensity(); + llvm::stable_sort(sortedSecs, [&](int a, int b) { + return clusters[a].getDensity() > clusters[b].getDensity(); }); - for (int SI : SortedSecs) { + for (int si : sortedSecs) { // Clusters[SI] is the same as SecToClusters[SI] here because it has not // been merged into another cluster yet. - Cluster &C = Clusters[SI]; + Cluster &c = clusters[si]; // Don't consider merging if the edge is unlikely. - if (C.BestPred.From == -1 || C.BestPred.Weight * 10 <= C.InitialWeight) + if (c.bestPred.from == -1 || c.bestPred.weight * 10 <= c.initialWeight) continue; - Cluster *PredC = SecToCluster[C.BestPred.From]; - if (PredC == &C) + Cluster *predC = secToCluster[c.bestPred.from]; + if (predC == &c) continue; - if (C.Size + PredC->Size > MAX_CLUSTER_SIZE) + if (c.size + predC->size > MAX_CLUSTER_SIZE) continue; - if (isNewDensityBad(*PredC, C)) + if (isNewDensityBad(*predC, c)) continue; // NOTE: Consider using a disjoint-set to track section -> cluster mapping // if this is ever slow. - for (int SI : C.Sections) - SecToCluster[SI] = PredC; + for (int si : c.sections) + secToCluster[si] = predC; - mergeClusters(*PredC, C); + mergeClusters(*predC, c); } // Remove empty or dead nodes. Invalidates all cluster indices. - llvm::erase_if(Clusters, [](const Cluster &C) { - return C.Size == 0 || C.Sections.empty(); + llvm::erase_if(clusters, [](const Cluster &c) { + return c.size == 0 || c.sections.empty(); }); // Sort by density. - llvm::stable_sort(Clusters, [](const Cluster &A, const Cluster &B) { - return A.getDensity() > B.getDensity(); + llvm::stable_sort(clusters, [](const Cluster &a, const Cluster &b) { + return a.getDensity() > b.getDensity(); }); } @@ -218,35 +218,35 @@ groupClusters(); // Generate order. - DenseMap OrderMap; - ssize_t CurOrder = 1; + DenseMap orderMap; + ssize_t curOrder = 1; - for (const Cluster &C : Clusters) - for (int SecIndex : C.Sections) - OrderMap[Sections[SecIndex]] = CurOrder++; - - if (!Config->PrintSymbolOrder.empty()) { - std::error_code EC; - raw_fd_ostream OS(Config->PrintSymbolOrder, EC, sys::fs::F_None); - if (EC) { - error("cannot open " + Config->PrintSymbolOrder + ": " + EC.message()); - return OrderMap; + for (const Cluster &c : clusters) + for (int secIndex : c.sections) + orderMap[sections[secIndex]] = curOrder++; + + if (!config->printSymbolOrder.empty()) { + std::error_code ec; + raw_fd_ostream os(config->printSymbolOrder, ec, sys::fs::F_None); + if (ec) { + error("cannot open " + config->printSymbolOrder + ": " + ec.message()); + return orderMap; } // Print the symbols ordered by C3, in the order of increasing CurOrder // Instead of sorting all the OrderMap, just repeat the loops above. - for (const Cluster &C : Clusters) - for (int SecIndex : C.Sections) + for (const Cluster &c : clusters) + for (int secIndex : c.sections) // Search all the symbols in the file of the section // and find out a Defined symbol with name that is within the section. - for (Symbol *Sym: Sections[SecIndex]->File->getSymbols()) - if (!Sym->isSection()) // Filter out section-type symbols here. - if (auto *D = dyn_cast(Sym)) - if (Sections[SecIndex] == D->Section) - OS << Sym->getName() << "\n"; + for (Symbol *sym: sections[secIndex]->file->getSymbols()) + if (!sym->isSection()) // Filter out section-type symbols here. + if (auto *d = dyn_cast(sym)) + if (sections[secIndex] == d->section) + os << sym->getName() << "\n"; } - return OrderMap; + return orderMap; } // Sort sections by the profile data provided by -callgraph-profile-file Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -62,17 +62,17 @@ enum class ARMVFPArgKind { Default, Base, VFP, ToolChain }; struct SymbolVersion { - llvm::StringRef Name; - bool IsExternCpp; - bool HasWildcard; + llvm::StringRef name; + bool isExternCpp; + bool hasWildcard; }; // This struct contains symbols version definition that // can be found in version script if it is used for link. struct VersionDefinition { - llvm::StringRef Name; - uint16_t Id = 0; - std::vector Globals; + llvm::StringRef name; + uint16_t id = 0; + std::vector globals; }; // This struct contains the global configuration for the linker. @@ -80,177 +80,177 @@ // and such fields have the same name as the corresponding options. // Most fields are initialized by the driver. struct Configuration { - uint8_t OSABI = 0; - uint32_t AndFeatures = 0; - llvm::CachePruningPolicy ThinLTOCachePolicy; - llvm::StringMap SectionStartMap; - llvm::StringRef Chroot; - llvm::StringRef DynamicLinker; - llvm::StringRef DwoDir; - llvm::StringRef Entry; - llvm::StringRef Emulation; - llvm::StringRef Fini; - llvm::StringRef Init; - llvm::StringRef LTOAAPipeline; - llvm::StringRef LTOCSProfileFile; - llvm::StringRef LTONewPmPasses; - llvm::StringRef LTOObjPath; - llvm::StringRef LTOSampleProfile; - llvm::StringRef MapFile; - llvm::StringRef OutputFile; - llvm::StringRef OptRemarksFilename; - llvm::StringRef OptRemarksPasses; - llvm::StringRef OptRemarksFormat; - llvm::StringRef ProgName; - llvm::StringRef PrintSymbolOrder; - llvm::StringRef SoName; - llvm::StringRef Sysroot; - llvm::StringRef ThinLTOCacheDir; - llvm::StringRef ThinLTOIndexOnlyArg; - std::pair ThinLTOObjectSuffixReplace; - std::pair ThinLTOPrefixReplace; - std::string Rpath; - std::vector VersionDefinitions; - std::vector AuxiliaryList; - std::vector FilterList; - std::vector SearchPaths; - std::vector SymbolOrderingFile; - std::vector Undefined; - std::vector DynamicList; - std::vector VersionScriptGlobals; - std::vector VersionScriptLocals; - std::vector BuildIdVector; + uint8_t osabi = 0; + uint32_t andFeatures = 0; + llvm::CachePruningPolicy thinLTOCachePolicy; + llvm::StringMap sectionStartMap; + llvm::StringRef chroot; + llvm::StringRef dynamicLinker; + llvm::StringRef dwoDir; + llvm::StringRef entry; + llvm::StringRef emulation; + llvm::StringRef fini; + llvm::StringRef init; + llvm::StringRef ltoAAPipeline; + llvm::StringRef ltoCSProfileFile; + llvm::StringRef ltoNewPmPasses; + llvm::StringRef ltoObjPath; + llvm::StringRef ltoSampleProfile; + llvm::StringRef mapFile; + llvm::StringRef outputFile; + llvm::StringRef optRemarksFilename; + llvm::StringRef optRemarksPasses; + llvm::StringRef optRemarksFormat; + llvm::StringRef progName; + llvm::StringRef printSymbolOrder; + llvm::StringRef soName; + llvm::StringRef sysroot; + llvm::StringRef thinLTOCacheDir; + llvm::StringRef thinLTOIndexOnlyArg; + std::pair thinLTOObjectSuffixReplace; + std::pair thinLTOPrefixReplace; + std::string rpath; + std::vector versionDefinitions; + std::vector auxiliaryList; + std::vector filterList; + std::vector searchPaths; + std::vector symbolOrderingFile; + std::vector undefined; + std::vector dynamicList; + std::vector versionScriptGlobals; + std::vector versionScriptLocals; + std::vector buildIdVector; llvm::MapVector, uint64_t> - CallGraphProfile; - bool AllowMultipleDefinition; - bool AllowShlibUndefined; - bool AndroidPackDynRelocs; - bool ARMHasBlx = false; - bool ARMHasMovtMovw = false; - bool ARMJ1J2BranchEncoding = false; - bool AsNeeded = false; - bool Bsymbolic; - bool BsymbolicFunctions; - bool CallGraphProfileSort; - bool CheckSections; - bool CompressDebugSections; - bool Cref; - bool DefineCommon; - bool Demangle = true; - bool DependentLibraries; - bool DisableVerify; - bool EhFrameHdr; - bool EmitLLVM; - bool EmitRelocs; - bool EnableNewDtags; - bool ExecuteOnly; - bool ExportDynamic; - bool FixCortexA53Errata843419; - bool ForceBTI; - bool FormatBinary = false; - bool RequireCET; - bool GcSections; - bool GdbIndex; - bool GnuHash = false; - bool GnuUnique; - bool HasDynamicList = false; - bool HasDynSymTab; - bool IgnoreDataAddressEquality; - bool IgnoreFunctionAddressEquality; - bool LTOCSProfileGenerate; - bool LTODebugPassManager; - bool LTONewPassManager; - bool MergeArmExidx; - bool MipsN32Abi = false; - bool Nmagic; - bool NoinhibitExec; - bool Nostdlib; - bool OFormatBinary; - bool Omagic; - bool OptRemarksWithHotness; - bool PacPlt; - bool PicThunk; - bool Pie; - bool PrintGcSections; - bool PrintIcfSections; - bool Relocatable; - bool RelrPackDynRelocs; - bool SaveTemps; - bool SingleRoRx; - bool Shared; - bool Static = false; - bool SysvHash = false; - bool Target1Rel; - bool Trace; - bool ThinLTOEmitImportsFiles; - bool ThinLTOIndexOnly; - bool TocOptimize; - bool UndefinedVersion; - bool UseAndroidRelrTags = false; - bool WarnBackrefs; - bool WarnCommon; - bool WarnIfuncTextrel; - bool WarnMissingEntry; - bool WarnSymbolOrdering; - bool WriteAddends; - bool ZCombreloc; - bool ZCopyreloc; - bool ZExecstack; - bool ZGlobal; - bool ZHazardplt; - bool ZIfuncNoplt; - bool ZInitfirst; - bool ZInterpose; - bool ZKeepTextSectionPrefix; - bool ZNodefaultlib; - bool ZNodelete; - bool ZNodlopen; - bool ZNow; - bool ZOrigin; - bool ZRelro; - bool ZRodynamic; - bool ZText; - bool ZRetpolineplt; - bool ZWxneeded; - DiscardPolicy Discard; - ICFLevel ICF; - OrphanHandlingPolicy OrphanHandling; - SortSectionPolicy SortSection; - StripPolicy Strip; - UnresolvedPolicy UnresolvedSymbols; - Target2Policy Target2; - ARMVFPArgKind ARMVFPArgs = ARMVFPArgKind::Default; - BuildIdKind BuildId = BuildIdKind::None; - ELFKind EKind = ELFNoneKind; - uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; - uint16_t EMachine = llvm::ELF::EM_NONE; - llvm::Optional ImageBase; - uint64_t CommonPageSize; - uint64_t MaxPageSize; - uint64_t MipsGotSize; - uint64_t ZStackSize; - unsigned LTOPartitions; - unsigned LTOO; - unsigned Optimize; - unsigned ThinLTOJobs; - int32_t SplitStackAdjustSize; + callGraphProfile; + bool allowMultipleDefinition; + bool allowShlibUndefined; + bool androidPackDynRelocs; + bool armHasBlx = false; + bool armHasMovtMovw = false; + bool armJ1J2BranchEncoding = false; + bool asNeeded = false; + bool bsymbolic; + bool bsymbolicFunctions; + bool callGraphProfileSort; + bool checkSections; + bool compressDebugSections; + bool cref; + bool defineCommon; + bool demangle = true; + bool dependentLibraries; + bool disableVerify; + bool ehFrameHdr; + bool emitLLVM; + bool emitRelocs; + bool enableNewDtags; + bool executeOnly; + bool exportDynamic; + bool fixCortexA53Errata843419; + bool forceBTI; + bool formatBinary = false; + bool requireCET; + bool gcSections; + bool gdbIndex; + bool gnuHash = false; + bool gnuUnique; + bool hasDynamicList = false; + bool hasDynSymTab; + bool ignoreDataAddressEquality; + bool ignoreFunctionAddressEquality; + bool ltoCSProfileGenerate; + bool ltoDebugPassManager; + bool ltoNewPassManager; + bool mergeArmExidx; + bool mipsN32Abi = false; + bool nmagic; + bool noinhibitExec; + bool nostdlib; + bool oFormatBinary; + bool omagic; + bool optRemarksWithHotness; + bool pacPlt; + bool picThunk; + bool pie; + bool printGcSections; + bool printIcfSections; + bool relocatable; + bool relrPackDynRelocs; + bool saveTemps; + bool singleRoRx; + bool shared; + bool isStatic = false; + bool sysvHash = false; + bool target1Rel; + bool trace; + bool thinLTOEmitImportsFiles; + bool thinLTOIndexOnly; + bool tocOptimize; + bool undefinedVersion; + bool useAndroidRelrTags = false; + bool warnBackrefs; + bool warnCommon; + bool warnIfuncTextrel; + bool warnMissingEntry; + bool warnSymbolOrdering; + bool writeAddends; + bool zCombreloc; + bool zCopyreloc; + bool zExecstack; + bool zGlobal; + bool zHazardplt; + bool zIfuncNoplt; + bool zInitfirst; + bool zInterpose; + bool zKeepTextSectionPrefix; + bool zNodefaultlib; + bool zNodelete; + bool zNodlopen; + bool zNow; + bool zOrigin; + bool zRelro; + bool zRodynamic; + bool zText; + bool zRetpolineplt; + bool zWxneeded; + DiscardPolicy discard; + ICFLevel icf; + OrphanHandlingPolicy orphanHandling; + SortSectionPolicy sortSection; + StripPolicy strip; + UnresolvedPolicy unresolvedSymbols; + Target2Policy target2; + ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default; + BuildIdKind buildId = BuildIdKind::None; + ELFKind ekind = ELFNoneKind; + uint16_t defaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; + uint16_t emachine = llvm::ELF::EM_NONE; + llvm::Optional imageBase; + uint64_t commonPageSize; + uint64_t maxPageSize; + uint64_t mipsGotSize; + uint64_t zStackSize; + unsigned ltoPartitions; + unsigned ltoo; + unsigned optimize; + unsigned thinLTOJobs; + int32_t splitStackAdjustSize; // The following config options do not directly correspond to any // particualr command line options. // True if we need to pass through relocations in input files to the // output file. Usually false because we consume relocations. - bool CopyRelocs; + bool copyRelocs; // True if the target is ELF64. False if ELF32. - bool Is64; + bool is64; // True if the target is little-endian. False if big-endian. - bool IsLE; + bool isLE; // endianness::little if IsLE is true. endianness::big otherwise. - llvm::support::endianness Endianness; + llvm::support::endianness endianness; // True if the target is the little-endian MIPS64. // @@ -264,7 +264,7 @@ // name whatever that means. A fun hypothesis is that "EL" is short for // little-endian written in the little-endian order, but I don't know // if that's true.) - bool IsMips64EL; + bool isMips64EL; // True if we need to set the DF_STATIC_TLS flag to an output file, // which works as a hint to the dynamic loader that the file contains @@ -278,10 +278,10 @@ // Since the flag is updated by multi-threaded code, we use std::atomic. // (Writing to a variable is not considered thread-safe even if the // variable is boolean and we always set the same value from all threads.) - std::atomic HasStaticTlsModel{false}; + std::atomic hasStaticTlsModel{false}; // Holds set of ELF header flags for the target. - uint32_t EFlags = 0; + uint32_t eflags = 0; // The ELF spec defines two types of relocation table entries, RELA and // REL. RELA is a triplet of (offset, info, addend) while REL is a @@ -297,23 +297,23 @@ // Each ABI defines its relocation type. IsRela is true if target // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A // few 32-bit ABIs are using RELA too. - bool IsRela; + bool isRela; // True if we are creating position-independent code. - bool Pic; + bool isPic; // 4 for ELF32, 8 for ELF64. - int Wordsize; + int wordsize; }; // The only instance of Configuration struct. -extern Configuration *Config; +extern Configuration *config; -static inline void errorOrWarn(const Twine &Msg) { - if (!Config->NoinhibitExec) - error(Msg); +static inline void errorOrWarn(const Twine &msg) { + if (!config->noinhibitExec) + error(msg); else - warn(Msg); + warn(msg); } } // namespace elf } // namespace lld Index: lld/trunk/ELF/DWARF.h =================================================================== --- lld/trunk/ELF/DWARF.h +++ lld/trunk/ELF/DWARF.h @@ -20,70 +20,70 @@ class InputSection; struct LLDDWARFSection final : public llvm::DWARFSection { - InputSectionBase *Sec = nullptr; + InputSectionBase *sec = nullptr; }; template class LLDDwarfObj final : public llvm::DWARFObject { public: - explicit LLDDwarfObj(ObjFile *Obj); + explicit LLDDwarfObj(ObjFile *obj); void forEachInfoSections( - llvm::function_ref F) const override { - F(InfoSection); + llvm::function_ref f) const override { + f(infoSection); } const llvm::DWARFSection &getRangeSection() const override { - return RangeSection; + return rangeSection; } const llvm::DWARFSection &getRnglistsSection() const override { - return RngListsSection; + return rngListsSection; } const llvm::DWARFSection &getLineSection() const override { - return LineSection; + return lineSection; } const llvm::DWARFSection &getAddrSection() const override { - return AddrSection; + return addrSection; } const llvm::DWARFSection &getGnuPubNamesSection() const override { - return GnuPubNamesSection; + return gnuPubNamesSection; } const llvm::DWARFSection &getGnuPubTypesSection() const override { - return GnuPubTypesSection; + return gnuPubTypesSection; } StringRef getFileName() const override { return ""; } - StringRef getAbbrevSection() const override { return AbbrevSection; } - StringRef getStringSection() const override { return StrSection; } - StringRef getLineStringSection() const override { return LineStringSection; } + StringRef getAbbrevSection() const override { return abbrevSection; } + StringRef getStringSection() const override { return strSection; } + StringRef getLineStringSection() const override { return lineStringSection; } bool isLittleEndian() const override { return ELFT::TargetEndianness == llvm::support::little; } - llvm::Optional find(const llvm::DWARFSection &Sec, - uint64_t Pos) const override; + llvm::Optional find(const llvm::DWARFSection &sec, + uint64_t pos) const override; private: template - llvm::Optional findAux(const InputSectionBase &Sec, - uint64_t Pos, - ArrayRef Rels) const; - - LLDDWARFSection GnuPubNamesSection; - LLDDWARFSection GnuPubTypesSection; - LLDDWARFSection InfoSection; - LLDDWARFSection RangeSection; - LLDDWARFSection RngListsSection; - LLDDWARFSection LineSection; - LLDDWARFSection AddrSection; - StringRef AbbrevSection; - StringRef StrSection; - StringRef LineStringSection; + llvm::Optional findAux(const InputSectionBase &sec, + uint64_t pos, + ArrayRef rels) const; + + LLDDWARFSection gnuPubNamesSection; + LLDDWARFSection gnuPubTypesSection; + LLDDWARFSection infoSection; + LLDDWARFSection rangeSection; + LLDDWARFSection rngListsSection; + LLDDWARFSection lineSection; + LLDDWARFSection addrSection; + StringRef abbrevSection; + StringRef strSection; + StringRef lineStringSection; }; } // namespace elf Index: lld/trunk/ELF/DWARF.cpp =================================================================== --- lld/trunk/ELF/DWARF.cpp +++ lld/trunk/ELF/DWARF.cpp @@ -25,32 +25,32 @@ using namespace lld; using namespace lld::elf; -template LLDDwarfObj::LLDDwarfObj(ObjFile *Obj) { - for (InputSectionBase *Sec : Obj->getSections()) { - if (!Sec) +template LLDDwarfObj::LLDDwarfObj(ObjFile *obj) { + for (InputSectionBase *sec : obj->getSections()) { + if (!sec) continue; - if (LLDDWARFSection *M = - StringSwitch(Sec->Name) - .Case(".debug_addr", &AddrSection) - .Case(".debug_gnu_pubnames", &GnuPubNamesSection) - .Case(".debug_gnu_pubtypes", &GnuPubTypesSection) - .Case(".debug_info", &InfoSection) - .Case(".debug_ranges", &RangeSection) - .Case(".debug_rnglists", &RngListsSection) - .Case(".debug_line", &LineSection) + if (LLDDWARFSection *m = + StringSwitch(sec->name) + .Case(".debug_addr", &addrSection) + .Case(".debug_gnu_pubnames", &gnuPubNamesSection) + .Case(".debug_gnu_pubtypes", &gnuPubTypesSection) + .Case(".debug_info", &infoSection) + .Case(".debug_ranges", &rangeSection) + .Case(".debug_rnglists", &rngListsSection) + .Case(".debug_line", &lineSection) .Default(nullptr)) { - M->Data = toStringRef(Sec->data()); - M->Sec = Sec; + m->Data = toStringRef(sec->data()); + m->sec = sec; continue; } - if (Sec->Name == ".debug_abbrev") - AbbrevSection = toStringRef(Sec->data()); - else if (Sec->Name == ".debug_str") - StrSection = toStringRef(Sec->data()); - else if (Sec->Name == ".debug_line_str") - LineStringSection = toStringRef(Sec->data()); + if (sec->name == ".debug_abbrev") + abbrevSection = toStringRef(sec->data()); + else if (sec->name == ".debug_str") + strSection = toStringRef(sec->data()); + else if (sec->name == ".debug_line_str") + lineStringSection = toStringRef(sec->data()); } } @@ -58,17 +58,17 @@ template struct LLDRelocationResolver { // In the ELF ABIs, S sepresents the value of the symbol in the relocation // entry. For Rela, the addend is stored as part of the relocation entry. - static uint64_t resolve(object::RelocationRef Ref, uint64_t S, + static uint64_t resolve(object::RelocationRef ref, uint64_t s, uint64_t /* A */) { - return S + Ref.getRawDataRefImpl().p; + return s + ref.getRawDataRefImpl().p; } }; template struct LLDRelocationResolver> { // For Rel, the addend A is supplied by the caller. - static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t S, - uint64_t A) { - return S + A; + static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s, + uint64_t a) { + return s + a; } }; } // namespace @@ -79,47 +79,47 @@ template template Optional -LLDDwarfObj::findAux(const InputSectionBase &Sec, uint64_t Pos, - ArrayRef Rels) const { - auto It = - partition_point(Rels, [=](const RelTy &A) { return A.r_offset < Pos; }); - if (It == Rels.end() || It->r_offset != Pos) +LLDDwarfObj::findAux(const InputSectionBase &sec, uint64_t pos, + ArrayRef rels) const { + auto it = + partition_point(rels, [=](const RelTy &a) { return a.r_offset < pos; }); + if (it == rels.end() || it->r_offset != pos) return None; - const RelTy &Rel = *It; + const RelTy &rel = *it; - const ObjFile *File = Sec.getFile(); - uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); - const typename ELFT::Sym &Sym = File->template getELFSyms()[SymIndex]; - uint32_t SecIndex = File->getSectionIndex(Sym); + const ObjFile *file = sec.getFile(); + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + const typename ELFT::Sym &sym = file->template getELFSyms()[symIndex]; + uint32_t secIndex = file->getSectionIndex(sym); // An undefined symbol may be a symbol defined in a discarded section. We // shall still resolve it. This is important for --gdb-index: the end address // offset of an entry in .debug_ranges is relocated. If it is not resolved, // its zero value will terminate the decoding of .debug_ranges prematurely. - Symbol &S = File->getRelocTargetSym(Rel); - uint64_t Val = 0; - if (auto *DR = dyn_cast(&S)) { - Val = DR->Value; + Symbol &s = file->getRelocTargetSym(rel); + uint64_t val = 0; + if (auto *dr = dyn_cast(&s)) { + val = dr->value; // FIXME: We should be consistent about always adding the file // offset or not. - if (DR->Section->Flags & ELF::SHF_ALLOC) - Val += cast(DR->Section)->getOffsetInFile(); + if (dr->section->flags & ELF::SHF_ALLOC) + val += cast(dr->section)->getOffsetInFile(); } - DataRefImpl D; - D.p = getAddend(Rel); - return RelocAddrEntry{SecIndex, RelocationRef(D, nullptr), - LLDRelocationResolver::resolve, Val}; + DataRefImpl d; + d.p = getAddend(rel); + return RelocAddrEntry{secIndex, RelocationRef(d, nullptr), + LLDRelocationResolver::resolve, val}; } template -Optional LLDDwarfObj::find(const llvm::DWARFSection &S, - uint64_t Pos) const { - auto &Sec = static_cast(S); - if (Sec.Sec->AreRelocsRela) - return findAux(*Sec.Sec, Pos, Sec.Sec->template relas()); - return findAux(*Sec.Sec, Pos, Sec.Sec->template rels()); +Optional LLDDwarfObj::find(const llvm::DWARFSection &s, + uint64_t pos) const { + auto &sec = static_cast(s); + if (sec.sec->areRelocsRela) + return findAux(*sec.sec, pos, sec.sec->template relas()); + return findAux(*sec.sec, pos, sec.sec->template rels()); } template class elf::LLDDwarfObj; Index: lld/trunk/ELF/Driver.h =================================================================== --- lld/trunk/ELF/Driver.h +++ lld/trunk/ELF/Driver.h @@ -22,37 +22,37 @@ namespace lld { namespace elf { -extern class LinkerDriver *Driver; +extern class LinkerDriver *driver; class LinkerDriver { public: - void main(ArrayRef Args); - void addFile(StringRef Path, bool WithLOption); - void addLibrary(StringRef Name); + void main(ArrayRef args); + void addFile(StringRef path, bool withLOption); + void addLibrary(StringRef name); private: - void createFiles(llvm::opt::InputArgList &Args); + void createFiles(llvm::opt::InputArgList &args); void inferMachineType(); - template void link(llvm::opt::InputArgList &Args); + template void link(llvm::opt::InputArgList &args); template void compileBitcodeFiles(); // True if we are in --whole-archive and --no-whole-archive. - bool InWholeArchive = false; + bool inWholeArchive = false; // True if we are in --start-lib and --end-lib. - bool InLib = false; + bool inLib = false; // For LTO. - std::unique_ptr LTO; + std::unique_ptr lto; - std::vector Files; + std::vector files; }; // Parses command line options. class ELFOptTable : public llvm::opt::OptTable { public: ELFOptTable(); - llvm::opt::InputArgList parse(ArrayRef Argv); + llvm::opt::InputArgList parse(ArrayRef argv); }; // Create enum with OPT_xxx values for each option in Options.td @@ -64,12 +64,12 @@ }; void printHelp(); -std::string createResponseFile(const llvm::opt::InputArgList &Args); +std::string createResponseFile(const llvm::opt::InputArgList &args); -llvm::Optional findFromSearchPaths(StringRef Path); -llvm::Optional searchScript(StringRef Path); -llvm::Optional searchLibraryBaseName(StringRef Path); -llvm::Optional searchLibrary(StringRef Path); +llvm::Optional findFromSearchPaths(StringRef path); +llvm::Optional searchScript(StringRef path); +llvm::Optional searchLibraryBaseName(StringRef path); +llvm::Optional searchLibrary(StringRef path); } // namespace elf } // namespace lld Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -68,49 +68,49 @@ using namespace lld; using namespace lld::elf; -Configuration *elf::Config; -LinkerDriver *elf::Driver; +Configuration *elf::config; +LinkerDriver *elf::driver; -static void setConfigs(opt::InputArgList &Args); -static void readConfigs(opt::InputArgList &Args); +static void setConfigs(opt::InputArgList &args); +static void readConfigs(opt::InputArgList &args); -bool elf::link(ArrayRef Args, bool CanExitEarly, - raw_ostream &Error) { - errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); +bool elf::link(ArrayRef args, bool canExitEarly, + raw_ostream &error) { + errorHandler().LogName = args::getFilenameWithoutExe(args[0]); errorHandler().ErrorLimitExceededMsg = "too many errors emitted, stopping now (use " "-error-limit=0 to see all errors)"; - errorHandler().ErrorOS = &Error; - errorHandler().ExitEarly = CanExitEarly; - errorHandler().ColorDiagnostics = Error.has_colors(); + errorHandler().ErrorOS = &error; + errorHandler().ExitEarly = canExitEarly; + errorHandler().ColorDiagnostics = error.has_colors(); - InputSections.clear(); - OutputSections.clear(); - BinaryFiles.clear(); - BitcodeFiles.clear(); - ObjectFiles.clear(); - SharedFiles.clear(); + inputSections.clear(); + outputSections.clear(); + binaryFiles.clear(); + bitcodeFiles.clear(); + objectFiles.clear(); + sharedFiles.clear(); - Config = make(); - Driver = make(); - Script = make(); - Symtab = make(); + config = make(); + driver = make(); + script = make(); + symtab = make(); - Tar = nullptr; - memset(&In, 0, sizeof(In)); + tar = nullptr; + memset(&in, 0, sizeof(in)); - Partitions = {Partition()}; + partitions = {Partition()}; - SharedFile::VernauxNum = 0; + SharedFile::vernauxNum = 0; - Config->ProgName = Args[0]; + config->progName = args[0]; - Driver->main(Args); + driver->main(args); // Exit immediately if we don't need to return to the caller. // This saves time because the overhead of calling destructors // for all globally-allocated objects is not negligible. - if (CanExitEarly) + if (canExitEarly) exitLld(errorCount() ? 1 : 0); freeArena(); @@ -118,16 +118,16 @@ } // Parses a linker -m option. -static std::tuple parseEmulation(StringRef Emul) { - uint8_t OSABI = 0; - StringRef S = Emul; - if (S.endswith("_fbsd")) { - S = S.drop_back(5); - OSABI = ELFOSABI_FREEBSD; +static std::tuple parseEmulation(StringRef emul) { + uint8_t osabi = 0; + StringRef s = emul; + if (s.endswith("_fbsd")) { + s = s.drop_back(5); + osabi = ELFOSABI_FREEBSD; } - std::pair Ret = - StringSwitch>(S) + std::pair ret = + StringSwitch>(s) .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec", {ELF64LEKind, EM_AARCH64}) .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM}) @@ -146,101 +146,101 @@ .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU}) .Default({ELFNoneKind, EM_NONE}); - if (Ret.first == ELFNoneKind) - error("unknown emulation: " + Emul); - return std::make_tuple(Ret.first, Ret.second, OSABI); + if (ret.first == ELFNoneKind) + error("unknown emulation: " + emul); + return std::make_tuple(ret.first, ret.second, osabi); } // Returns slices of MB by parsing MB as an archive file. // Each slice consists of a member file in the archive. std::vector> static getArchiveMembers( - MemoryBufferRef MB) { - std::unique_ptr File = - CHECK(Archive::create(MB), - MB.getBufferIdentifier() + ": failed to parse archive"); - - std::vector> V; - Error Err = Error::success(); - bool AddToTar = File->isThin() && Tar; - for (const ErrorOr &COrErr : File->children(Err)) { - Archive::Child C = - CHECK(COrErr, MB.getBufferIdentifier() + + MemoryBufferRef mb) { + std::unique_ptr file = + CHECK(Archive::create(mb), + mb.getBufferIdentifier() + ": failed to parse archive"); + + std::vector> v; + Error err = Error::success(); + bool addToTar = file->isThin() && tar; + for (const ErrorOr &cOrErr : file->children(err)) { + Archive::Child c = + CHECK(cOrErr, mb.getBufferIdentifier() + ": could not get the child of the archive"); - MemoryBufferRef MBRef = - CHECK(C.getMemoryBufferRef(), - MB.getBufferIdentifier() + + MemoryBufferRef mbref = + CHECK(c.getMemoryBufferRef(), + mb.getBufferIdentifier() + ": could not get the buffer for a child of the archive"); - if (AddToTar) - Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer()); - V.push_back(std::make_pair(MBRef, C.getChildOffset())); - } - if (Err) - fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + - toString(std::move(Err))); + if (addToTar) + tar->append(relativeToRoot(check(c.getFullName())), mbref.getBuffer()); + v.push_back(std::make_pair(mbref, c.getChildOffset())); + } + if (err) + fatal(mb.getBufferIdentifier() + ": Archive::children failed: " + + toString(std::move(err))); // Take ownership of memory buffers created for members of thin archives. - for (std::unique_ptr &MB : File->takeThinBuffers()) - make>(std::move(MB)); + for (std::unique_ptr &mb : file->takeThinBuffers()) + make>(std::move(mb)); - return V; + return v; } // Opens a file and create a file object. Path has to be resolved already. -void LinkerDriver::addFile(StringRef Path, bool WithLOption) { +void LinkerDriver::addFile(StringRef path, bool withLOption) { using namespace sys::fs; - Optional Buffer = readFile(Path); - if (!Buffer.hasValue()) + Optional buffer = readFile(path); + if (!buffer.hasValue()) return; - MemoryBufferRef MBRef = *Buffer; + MemoryBufferRef mbref = *buffer; - if (Config->FormatBinary) { - Files.push_back(make(MBRef)); + if (config->formatBinary) { + files.push_back(make(mbref)); return; } - switch (identify_magic(MBRef.getBuffer())) { + switch (identify_magic(mbref.getBuffer())) { case file_magic::unknown: - readLinkerScript(MBRef); + readLinkerScript(mbref); return; case file_magic::archive: { // Handle -whole-archive. - if (InWholeArchive) { - for (const auto &P : getArchiveMembers(MBRef)) - Files.push_back(createObjectFile(P.first, Path, P.second)); + if (inWholeArchive) { + for (const auto &p : getArchiveMembers(mbref)) + files.push_back(createObjectFile(p.first, path, p.second)); return; } - std::unique_ptr File = - CHECK(Archive::create(MBRef), Path + ": failed to parse archive"); + std::unique_ptr file = + CHECK(Archive::create(mbref), path + ": failed to parse archive"); // If an archive file has no symbol table, it is likely that a user // is attempting LTO and using a default ar command that doesn't // understand the LLVM bitcode file. It is a pretty common error, so // we'll handle it as if it had a symbol table. - if (!File->isEmpty() && !File->hasSymbolTable()) { + if (!file->isEmpty() && !file->hasSymbolTable()) { // Check if all members are bitcode files. If not, ignore, which is the // default action without the LTO hack described above. - for (const std::pair &P : - getArchiveMembers(MBRef)) - if (identify_magic(P.first.getBuffer()) != file_magic::bitcode) { - error(Path + ": archive has no index; run ranlib to add one"); + for (const std::pair &p : + getArchiveMembers(mbref)) + if (identify_magic(p.first.getBuffer()) != file_magic::bitcode) { + error(path + ": archive has no index; run ranlib to add one"); return; } - for (const std::pair &P : - getArchiveMembers(MBRef)) - Files.push_back(make(P.first, Path, P.second)); + for (const std::pair &p : + getArchiveMembers(mbref)) + files.push_back(make(p.first, path, p.second)); return; } // Handle the regular case. - Files.push_back(make(std::move(File))); + files.push_back(make(std::move(file))); return; } case file_magic::elf_shared_object: - if (Config->Static || Config->Relocatable) { - error("attempted static link of dynamic object " + Path); + if (config->isStatic || config->relocatable) { + error("attempted static link of dynamic object " + path); return; } @@ -254,27 +254,27 @@ // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. - Files.push_back( - make(MBRef, WithLOption ? path::filename(Path) : Path)); + files.push_back( + make(mbref, withLOption ? path::filename(path) : path)); return; case file_magic::bitcode: case file_magic::elf_relocatable: - if (InLib) - Files.push_back(make(MBRef, "", 0)); + if (inLib) + files.push_back(make(mbref, "", 0)); else - Files.push_back(createObjectFile(MBRef)); + files.push_back(createObjectFile(mbref)); break; default: - error(Path + ": unknown file type"); + error(path + ": unknown file type"); } } // Add a given library by searching it from input search paths. -void LinkerDriver::addLibrary(StringRef Name) { - if (Optional Path = searchLibrary(Name)) - addFile(*Path, /*WithLOption=*/true); +void LinkerDriver::addLibrary(StringRef name) { + if (Optional path = searchLibrary(name)) + addFile(*path, /*WithLOption=*/true); else - error("unable to find library -l" + Name); + error("unable to find library -l" + name); } // This function is called on startup. We need this for LTO since @@ -293,117 +293,117 @@ static void checkOptions() { // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup // table which is a relatively new feature. - if (Config->EMachine == EM_MIPS && Config->GnuHash) + if (config->emachine == EM_MIPS && config->gnuHash) error("the .gnu.hash section is not compatible with the MIPS target"); - if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64) + if (config->fixCortexA53Errata843419 && config->emachine != EM_AARCH64) error("--fix-cortex-a53-843419 is only supported on AArch64 targets"); - if (Config->TocOptimize && Config->EMachine != EM_PPC64) + if (config->tocOptimize && config->emachine != EM_PPC64) error("--toc-optimize is only supported on the PowerPC64 target"); - if (Config->Pie && Config->Shared) + if (config->pie && config->shared) error("-shared and -pie may not be used together"); - if (!Config->Shared && !Config->FilterList.empty()) + if (!config->shared && !config->filterList.empty()) error("-F may not be used without -shared"); - if (!Config->Shared && !Config->AuxiliaryList.empty()) + if (!config->shared && !config->auxiliaryList.empty()) error("-f may not be used without -shared"); - if (!Config->Relocatable && !Config->DefineCommon) + if (!config->relocatable && !config->defineCommon) error("-no-define-common not supported in non relocatable output"); - if (Config->ZText && Config->ZIfuncNoplt) + if (config->zText && config->zIfuncNoplt) error("-z text and -z ifunc-noplt may not be used together"); - if (Config->Relocatable) { - if (Config->Shared) + if (config->relocatable) { + if (config->shared) error("-r and -shared may not be used together"); - if (Config->GcSections) + if (config->gcSections) error("-r and --gc-sections may not be used together"); - if (Config->GdbIndex) + if (config->gdbIndex) error("-r and --gdb-index may not be used together"); - if (Config->ICF != ICFLevel::None) + if (config->icf != ICFLevel::None) error("-r and --icf may not be used together"); - if (Config->Pie) + if (config->pie) error("-r and -pie may not be used together"); } - if (Config->ExecuteOnly) { - if (Config->EMachine != EM_AARCH64) + if (config->executeOnly) { + if (config->emachine != EM_AARCH64) error("-execute-only is only supported on AArch64 targets"); - if (Config->SingleRoRx && !Script->HasSectionsCommand) + if (config->singleRoRx && !script->hasSectionsCommand) error("-execute-only and -no-rosegment cannot be used together"); } - if (Config->ZRetpolineplt && Config->RequireCET) + if (config->zRetpolineplt && config->requireCET) error("--require-cet may not be used with -z retpolineplt"); - if (Config->EMachine != EM_AARCH64) { - if (Config->PacPlt) + if (config->emachine != EM_AARCH64) { + if (config->pacPlt) error("--pac-plt only supported on AArch64"); - if (Config->ForceBTI) + if (config->forceBTI) error("--force-bti only supported on AArch64"); } } -static const char *getReproduceOption(opt::InputArgList &Args) { - if (auto *Arg = Args.getLastArg(OPT_reproduce)) - return Arg->getValue(); +static const char *getReproduceOption(opt::InputArgList &args) { + if (auto *arg = args.getLastArg(OPT_reproduce)) + return arg->getValue(); return getenv("LLD_REPRODUCE"); } -static bool hasZOption(opt::InputArgList &Args, StringRef Key) { - for (auto *Arg : Args.filtered(OPT_z)) - if (Key == Arg->getValue()) +static bool hasZOption(opt::InputArgList &args, StringRef key) { + for (auto *arg : args.filtered(OPT_z)) + if (key == arg->getValue()) return true; return false; } -static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2, +static bool getZFlag(opt::InputArgList &args, StringRef k1, StringRef k2, bool Default) { - for (auto *Arg : Args.filtered_reverse(OPT_z)) { - if (K1 == Arg->getValue()) + for (auto *arg : args.filtered_reverse(OPT_z)) { + if (k1 == arg->getValue()) return true; - if (K2 == Arg->getValue()) + if (k2 == arg->getValue()) return false; } return Default; } -static bool isKnownZFlag(StringRef S) { - return S == "combreloc" || S == "copyreloc" || S == "defs" || - S == "execstack" || S == "global" || S == "hazardplt" || - S == "ifunc-noplt" || S == "initfirst" || S == "interpose" || - S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" || - S == "nocombreloc" || S == "nocopyreloc" || S == "nodefaultlib" || - S == "nodelete" || S == "nodlopen" || S == "noexecstack" || - S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" || - S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" || - S == "rodynamic" || S == "text" || S == "wxneeded" || - S.startswith("common-page-size") || S.startswith("max-page-size=") || - S.startswith("stack-size="); +static bool isKnownZFlag(StringRef s) { + return s == "combreloc" || s == "copyreloc" || s == "defs" || + s == "execstack" || s == "global" || s == "hazardplt" || + s == "ifunc-noplt" || s == "initfirst" || s == "interpose" || + s == "keep-text-section-prefix" || s == "lazy" || s == "muldefs" || + s == "nocombreloc" || s == "nocopyreloc" || s == "nodefaultlib" || + s == "nodelete" || s == "nodlopen" || s == "noexecstack" || + s == "nokeep-text-section-prefix" || s == "norelro" || s == "notext" || + s == "now" || s == "origin" || s == "relro" || s == "retpolineplt" || + s == "rodynamic" || s == "text" || s == "wxneeded" || + s.startswith("common-page-size") || s.startswith("max-page-size=") || + s.startswith("stack-size="); } // Report an error for an unknown -z option. -static void checkZOptions(opt::InputArgList &Args) { - for (auto *Arg : Args.filtered(OPT_z)) - if (!isKnownZFlag(Arg->getValue())) - error("unknown -z value: " + StringRef(Arg->getValue())); +static void checkZOptions(opt::InputArgList &args) { + for (auto *arg : args.filtered(OPT_z)) + if (!isKnownZFlag(arg->getValue())) + error("unknown -z value: " + StringRef(arg->getValue())); } -void LinkerDriver::main(ArrayRef ArgsArr) { - ELFOptTable Parser; - opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); +void LinkerDriver::main(ArrayRef argsArr) { + ELFOptTable parser; + opt::InputArgList args = parser.parse(argsArr.slice(1)); // Interpret this flag early because error() depends on them. - errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); - checkZOptions(Args); + errorHandler().ErrorLimit = args::getInteger(args, OPT_error_limit, 20); + checkZOptions(args); // Handle -help - if (Args.hasArg(OPT_help)) { + if (args.hasArg(OPT_help)) { printHelp(); return; } @@ -423,39 +423,39 @@ // lot of "configure" scripts out there that are generated by old version // of Libtool. We cannot convince every software developer to migrate to // the latest version and re-generate scripts. So we have this hack. - if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) + if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) message(getLLDVersion() + " (compatible with GNU linkers)"); - if (const char *Path = getReproduceOption(Args)) { + if (const char *path = getReproduceOption(args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. - Expected> ErrOrWriter = - TarWriter::create(Path, path::stem(Path)); - if (ErrOrWriter) { - Tar = std::move(*ErrOrWriter); - Tar->append("response.txt", createResponseFile(Args)); - Tar->append("version.txt", getLLDVersion() + "\n"); + Expected> errOrWriter = + TarWriter::create(path, path::stem(path)); + if (errOrWriter) { + tar = std::move(*errOrWriter); + tar->append("response.txt", createResponseFile(args)); + tar->append("version.txt", getLLDVersion() + "\n"); } else { - error("--reproduce: " + toString(ErrOrWriter.takeError())); + error("--reproduce: " + toString(errOrWriter.takeError())); } } - readConfigs(Args); + readConfigs(args); // The behavior of -v or --version is a bit strange, but this is // needed for compatibility with GNU linkers. - if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) + if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT)) return; - if (Args.hasArg(OPT_version)) + if (args.hasArg(OPT_version)) return; initLLVM(); - createFiles(Args); + createFiles(args); if (errorCount()) return; inferMachineType(); - setConfigs(Args); + setConfigs(args); checkOptions(); if (errorCount()) return; @@ -463,178 +463,178 @@ // The Target instance handles target-specific stuff, such as applying // relocations or writing a PLT section. It also contains target-dependent // values such as a default image base address. - Target = getTarget(); + target = getTarget(); - switch (Config->EKind) { + switch (config->ekind) { case ELF32LEKind: - link(Args); + link(args); return; case ELF32BEKind: - link(Args); + link(args); return; case ELF64LEKind: - link(Args); + link(args); return; case ELF64BEKind: - link(Args); + link(args); return; default: llvm_unreachable("unknown Config->EKind"); } } -static std::string getRpath(opt::InputArgList &Args) { - std::vector V = args::getStrings(Args, OPT_rpath); - return llvm::join(V.begin(), V.end(), ":"); +static std::string getRpath(opt::InputArgList &args) { + std::vector v = args::getStrings(args, OPT_rpath); + return llvm::join(v.begin(), v.end(), ":"); } // Determines what we should do if there are remaining unresolved // symbols after the name resolution. -static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { - UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols, +static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) { + UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols, OPT_warn_unresolved_symbols, true) ? UnresolvedPolicy::ReportError : UnresolvedPolicy::Warn; // Process the last of -unresolved-symbols, -no-undefined or -z defs. - for (auto *Arg : llvm::reverse(Args)) { - switch (Arg->getOption().getID()) { + for (auto *arg : llvm::reverse(args)) { + switch (arg->getOption().getID()) { case OPT_unresolved_symbols: { - StringRef S = Arg->getValue(); - if (S == "ignore-all" || S == "ignore-in-object-files") + StringRef s = arg->getValue(); + if (s == "ignore-all" || s == "ignore-in-object-files") return UnresolvedPolicy::Ignore; - if (S == "ignore-in-shared-libs" || S == "report-all") - return ErrorOrWarn; - error("unknown --unresolved-symbols value: " + S); + if (s == "ignore-in-shared-libs" || s == "report-all") + return errorOrWarn; + error("unknown --unresolved-symbols value: " + s); continue; } case OPT_no_undefined: - return ErrorOrWarn; + return errorOrWarn; case OPT_z: - if (StringRef(Arg->getValue()) == "defs") - return ErrorOrWarn; + if (StringRef(arg->getValue()) == "defs") + return errorOrWarn; continue; } } // -shared implies -unresolved-symbols=ignore-all because missing // symbols are likely to be resolved at runtime using other DSOs. - if (Config->Shared) + if (config->shared) return UnresolvedPolicy::Ignore; - return ErrorOrWarn; + return errorOrWarn; } -static Target2Policy getTarget2(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_target2, "got-rel"); - if (S == "rel") +static Target2Policy getTarget2(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_target2, "got-rel"); + if (s == "rel") return Target2Policy::Rel; - if (S == "abs") + if (s == "abs") return Target2Policy::Abs; - if (S == "got-rel") + if (s == "got-rel") return Target2Policy::GotRel; - error("unknown --target2 option: " + S); + error("unknown --target2 option: " + s); return Target2Policy::GotRel; } -static bool isOutputFormatBinary(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_oformat, "elf"); - if (S == "binary") +static bool isOutputFormatBinary(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_oformat, "elf"); + if (s == "binary") return true; - if (!S.startswith("elf")) - error("unknown --oformat value: " + S); + if (!s.startswith("elf")) + error("unknown --oformat value: " + s); return false; } -static DiscardPolicy getDiscard(opt::InputArgList &Args) { - if (Args.hasArg(OPT_relocatable)) +static DiscardPolicy getDiscard(opt::InputArgList &args) { + if (args.hasArg(OPT_relocatable)) return DiscardPolicy::None; - auto *Arg = - Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); - if (!Arg) + auto *arg = + args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none); + if (!arg) return DiscardPolicy::Default; - if (Arg->getOption().getID() == OPT_discard_all) + if (arg->getOption().getID() == OPT_discard_all) return DiscardPolicy::All; - if (Arg->getOption().getID() == OPT_discard_locals) + if (arg->getOption().getID() == OPT_discard_locals) return DiscardPolicy::Locals; return DiscardPolicy::None; } -static StringRef getDynamicLinker(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); - if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker) +static StringRef getDynamicLinker(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); + if (!arg || arg->getOption().getID() == OPT_no_dynamic_linker) return ""; - return Arg->getValue(); + return arg->getValue(); } -static ICFLevel getICF(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all); - if (!Arg || Arg->getOption().getID() == OPT_icf_none) +static ICFLevel getICF(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all); + if (!arg || arg->getOption().getID() == OPT_icf_none) return ICFLevel::None; - if (Arg->getOption().getID() == OPT_icf_safe) + if (arg->getOption().getID() == OPT_icf_safe) return ICFLevel::Safe; return ICFLevel::All; } -static StripPolicy getStrip(opt::InputArgList &Args) { - if (Args.hasArg(OPT_relocatable)) +static StripPolicy getStrip(opt::InputArgList &args) { + if (args.hasArg(OPT_relocatable)) return StripPolicy::None; - auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug); - if (!Arg) + auto *arg = args.getLastArg(OPT_strip_all, OPT_strip_debug); + if (!arg) return StripPolicy::None; - if (Arg->getOption().getID() == OPT_strip_all) + if (arg->getOption().getID() == OPT_strip_all) return StripPolicy::All; return StripPolicy::Debug; } -static uint64_t parseSectionAddress(StringRef S, opt::InputArgList &Args, - const opt::Arg &Arg) { - uint64_t VA = 0; - if (S.startswith("0x")) - S = S.drop_front(2); - if (!to_integer(S, VA, 16)) - error("invalid argument: " + Arg.getAsString(Args)); - return VA; -} - -static StringMap getSectionStartMap(opt::InputArgList &Args) { - StringMap Ret; - for (auto *Arg : Args.filtered(OPT_section_start)) { - StringRef Name; - StringRef Addr; - std::tie(Name, Addr) = StringRef(Arg->getValue()).split('='); - Ret[Name] = parseSectionAddress(Addr, Args, *Arg); - } - - if (auto *Arg = Args.getLastArg(OPT_Ttext)) - Ret[".text"] = parseSectionAddress(Arg->getValue(), Args, *Arg); - if (auto *Arg = Args.getLastArg(OPT_Tdata)) - Ret[".data"] = parseSectionAddress(Arg->getValue(), Args, *Arg); - if (auto *Arg = Args.getLastArg(OPT_Tbss)) - Ret[".bss"] = parseSectionAddress(Arg->getValue(), Args, *Arg); - return Ret; -} - -static SortSectionPolicy getSortSection(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_sort_section); - if (S == "alignment") +static uint64_t parseSectionAddress(StringRef s, opt::InputArgList &args, + const opt::Arg &arg) { + uint64_t va = 0; + if (s.startswith("0x")) + s = s.drop_front(2); + if (!to_integer(s, va, 16)) + error("invalid argument: " + arg.getAsString(args)); + return va; +} + +static StringMap getSectionStartMap(opt::InputArgList &args) { + StringMap ret; + for (auto *arg : args.filtered(OPT_section_start)) { + StringRef name; + StringRef addr; + std::tie(name, addr) = StringRef(arg->getValue()).split('='); + ret[name] = parseSectionAddress(addr, args, *arg); + } + + if (auto *arg = args.getLastArg(OPT_Ttext)) + ret[".text"] = parseSectionAddress(arg->getValue(), args, *arg); + if (auto *arg = args.getLastArg(OPT_Tdata)) + ret[".data"] = parseSectionAddress(arg->getValue(), args, *arg); + if (auto *arg = args.getLastArg(OPT_Tbss)) + ret[".bss"] = parseSectionAddress(arg->getValue(), args, *arg); + return ret; +} + +static SortSectionPolicy getSortSection(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_sort_section); + if (s == "alignment") return SortSectionPolicy::Alignment; - if (S == "name") + if (s == "name") return SortSectionPolicy::Name; - if (!S.empty()) - error("unknown --sort-section rule: " + S); + if (!s.empty()) + error("unknown --sort-section rule: " + s); return SortSectionPolicy::Default; } -static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_orphan_handling, "place"); - if (S == "warn") +static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_orphan_handling, "place"); + if (s == "warn") return OrphanHandlingPolicy::Warn; - if (S == "error") + if (s == "error") return OrphanHandlingPolicy::Error; - if (S != "place") - error("unknown --orphan-handling mode: " + S); + if (s != "place") + error("unknown --orphan-handling mode: " + s); return OrphanHandlingPolicy::Place; } @@ -642,410 +642,410 @@ // synonym for "sha1" because all our hash functions including // -build-id=sha1 are actually tree hashes for performance reasons. static std::pair> -getBuildId(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_build_id, OPT_build_id_eq); - if (!Arg) +getBuildId(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_build_id, OPT_build_id_eq); + if (!arg) return {BuildIdKind::None, {}}; - if (Arg->getOption().getID() == OPT_build_id) + if (arg->getOption().getID() == OPT_build_id) return {BuildIdKind::Fast, {}}; - StringRef S = Arg->getValue(); - if (S == "fast") + StringRef s = arg->getValue(); + if (s == "fast") return {BuildIdKind::Fast, {}}; - if (S == "md5") + if (s == "md5") return {BuildIdKind::Md5, {}}; - if (S == "sha1" || S == "tree") + if (s == "sha1" || s == "tree") return {BuildIdKind::Sha1, {}}; - if (S == "uuid") + if (s == "uuid") return {BuildIdKind::Uuid, {}}; - if (S.startswith("0x")) - return {BuildIdKind::Hexstring, parseHex(S.substr(2))}; + if (s.startswith("0x")) + return {BuildIdKind::Hexstring, parseHex(s.substr(2))}; - if (S != "none") - error("unknown --build-id style: " + S); + if (s != "none") + error("unknown --build-id style: " + s); return {BuildIdKind::None, {}}; } -static std::pair getPackDynRelocs(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_pack_dyn_relocs, "none"); - if (S == "android") +static std::pair getPackDynRelocs(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_pack_dyn_relocs, "none"); + if (s == "android") return {true, false}; - if (S == "relr") + if (s == "relr") return {false, true}; - if (S == "android+relr") + if (s == "android+relr") return {true, true}; - if (S != "none") - error("unknown -pack-dyn-relocs format: " + S); + if (s != "none") + error("unknown -pack-dyn-relocs format: " + s); return {false, false}; } -static void readCallGraph(MemoryBufferRef MB) { +static void readCallGraph(MemoryBufferRef mb) { // Build a map from symbol name to section - DenseMap Map; - for (InputFile *File : ObjectFiles) - for (Symbol *Sym : File->getSymbols()) - Map[Sym->getName()] = Sym; - - auto FindSection = [&](StringRef Name) -> InputSectionBase * { - Symbol *Sym = Map.lookup(Name); - if (!Sym) { - if (Config->WarnSymbolOrdering) - warn(MB.getBufferIdentifier() + ": no such symbol: " + Name); + DenseMap map; + for (InputFile *file : objectFiles) + for (Symbol *sym : file->getSymbols()) + map[sym->getName()] = sym; + + auto findSection = [&](StringRef name) -> InputSectionBase * { + Symbol *sym = map.lookup(name); + if (!sym) { + if (config->warnSymbolOrdering) + warn(mb.getBufferIdentifier() + ": no such symbol: " + name); return nullptr; } - maybeWarnUnorderableSymbol(Sym); + maybeWarnUnorderableSymbol(sym); - if (Defined *DR = dyn_cast_or_null(Sym)) - return dyn_cast_or_null(DR->Section); + if (Defined *dr = dyn_cast_or_null(sym)) + return dyn_cast_or_null(dr->section); return nullptr; }; - for (StringRef Line : args::getLines(MB)) { - SmallVector Fields; - Line.split(Fields, ' '); - uint64_t Count; + for (StringRef line : args::getLines(mb)) { + SmallVector fields; + line.split(fields, ' '); + uint64_t count; - if (Fields.size() != 3 || !to_integer(Fields[2], Count)) { - error(MB.getBufferIdentifier() + ": parse error"); + if (fields.size() != 3 || !to_integer(fields[2], count)) { + error(mb.getBufferIdentifier() + ": parse error"); return; } - if (InputSectionBase *From = FindSection(Fields[0])) - if (InputSectionBase *To = FindSection(Fields[1])) - Config->CallGraphProfile[std::make_pair(From, To)] += Count; + if (InputSectionBase *from = findSection(fields[0])) + if (InputSectionBase *to = findSection(fields[1])) + config->callGraphProfile[std::make_pair(from, to)] += count; } } template static void readCallGraphsFromObjectFiles() { - for (auto File : ObjectFiles) { - auto *Obj = cast>(File); + for (auto file : objectFiles) { + auto *obj = cast>(file); - for (const Elf_CGProfile_Impl &CGPE : Obj->CGProfile) { - auto *FromSym = dyn_cast(&Obj->getSymbol(CGPE.cgp_from)); - auto *ToSym = dyn_cast(&Obj->getSymbol(CGPE.cgp_to)); - if (!FromSym || !ToSym) + for (const Elf_CGProfile_Impl &cgpe : obj->cgProfile) { + auto *fromSym = dyn_cast(&obj->getSymbol(cgpe.cgp_from)); + auto *toSym = dyn_cast(&obj->getSymbol(cgpe.cgp_to)); + if (!fromSym || !toSym) continue; - auto *From = dyn_cast_or_null(FromSym->Section); - auto *To = dyn_cast_or_null(ToSym->Section); - if (From && To) - Config->CallGraphProfile[{From, To}] += CGPE.cgp_weight; + auto *from = dyn_cast_or_null(fromSym->section); + auto *to = dyn_cast_or_null(toSym->section); + if (from && to) + config->callGraphProfile[{from, to}] += cgpe.cgp_weight; } } } -static bool getCompressDebugSections(opt::InputArgList &Args) { - StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none"); - if (S == "none") +static bool getCompressDebugSections(opt::InputArgList &args) { + StringRef s = args.getLastArgValue(OPT_compress_debug_sections, "none"); + if (s == "none") return false; - if (S != "zlib") - error("unknown --compress-debug-sections value: " + S); + if (s != "zlib") + error("unknown --compress-debug-sections value: " + s); if (!zlib::isAvailable()) error("--compress-debug-sections: zlib is not available"); return true; } -static std::pair getOldNewOptions(opt::InputArgList &Args, - unsigned Id) { - auto *Arg = Args.getLastArg(Id); - if (!Arg) +static std::pair getOldNewOptions(opt::InputArgList &args, + unsigned id) { + auto *arg = args.getLastArg(id); + if (!arg) return {"", ""}; - StringRef S = Arg->getValue(); - std::pair Ret = S.split(';'); - if (Ret.second.empty()) - error(Arg->getSpelling() + " expects 'old;new' format, but got " + S); - return Ret; + StringRef s = arg->getValue(); + std::pair ret = s.split(';'); + if (ret.second.empty()) + error(arg->getSpelling() + " expects 'old;new' format, but got " + s); + return ret; } // Parse the symbol ordering file and warn for any duplicate entries. -static std::vector getSymbolOrderingFile(MemoryBufferRef MB) { - SetVector Names; - for (StringRef S : args::getLines(MB)) - if (!Names.insert(S) && Config->WarnSymbolOrdering) - warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S); +static std::vector getSymbolOrderingFile(MemoryBufferRef mb) { + SetVector names; + for (StringRef s : args::getLines(mb)) + if (!names.insert(s) && config->warnSymbolOrdering) + warn(mb.getBufferIdentifier() + ": duplicate ordered symbol: " + s); - return Names.takeVector(); + return names.takeVector(); } -static void parseClangOption(StringRef Opt, const Twine &Msg) { - std::string Err; - raw_string_ostream OS(Err); +static void parseClangOption(StringRef opt, const Twine &msg) { + std::string err; + raw_string_ostream os(err); - const char *Argv[] = {Config->ProgName.data(), Opt.data()}; - if (cl::ParseCommandLineOptions(2, Argv, "", &OS)) + const char *argv[] = {config->progName.data(), opt.data()}; + if (cl::ParseCommandLineOptions(2, argv, "", &os)) return; - OS.flush(); - error(Msg + ": " + StringRef(Err).trim()); + os.flush(); + error(msg + ": " + StringRef(err).trim()); } // Initializes Config members by the command line options. -static void readConfigs(opt::InputArgList &Args) { - errorHandler().Verbose = Args.hasArg(OPT_verbose); +static void readConfigs(opt::InputArgList &args) { + errorHandler().Verbose = args.hasArg(OPT_verbose); errorHandler().FatalWarnings = - Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); - ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); + args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); + ThreadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); - Config->AllowMultipleDefinition = - Args.hasFlag(OPT_allow_multiple_definition, + config->allowMultipleDefinition = + args.hasFlag(OPT_allow_multiple_definition, OPT_no_allow_multiple_definition, false) || - hasZOption(Args, "muldefs"); - Config->AllowShlibUndefined = - Args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined, - Args.hasArg(OPT_shared)); - Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); - Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); - Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); - Config->CheckSections = - Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); - Config->Chroot = Args.getLastArgValue(OPT_chroot); - Config->CompressDebugSections = getCompressDebugSections(Args); - Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false); - Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common, - !Args.hasArg(OPT_relocatable)); - Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); - Config->DependentLibraries = Args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true); - Config->DisableVerify = Args.hasArg(OPT_disable_verify); - Config->Discard = getDiscard(Args); - Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq); - Config->DynamicLinker = getDynamicLinker(Args); - Config->EhFrameHdr = - Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); - Config->EmitLLVM = Args.hasArg(OPT_plugin_opt_emit_llvm, false); - Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); - Config->CallGraphProfileSort = Args.hasFlag( + hasZOption(args, "muldefs"); + config->allowShlibUndefined = + args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined, + args.hasArg(OPT_shared)); + config->auxiliaryList = args::getStrings(args, OPT_auxiliary); + config->bsymbolic = args.hasArg(OPT_Bsymbolic); + config->bsymbolicFunctions = args.hasArg(OPT_Bsymbolic_functions); + config->checkSections = + args.hasFlag(OPT_check_sections, OPT_no_check_sections, true); + config->chroot = args.getLastArgValue(OPT_chroot); + config->compressDebugSections = getCompressDebugSections(args); + config->cref = args.hasFlag(OPT_cref, OPT_no_cref, false); + config->defineCommon = args.hasFlag(OPT_define_common, OPT_no_define_common, + !args.hasArg(OPT_relocatable)); + config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true); + config->dependentLibraries = args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true); + config->disableVerify = args.hasArg(OPT_disable_verify); + config->discard = getDiscard(args); + config->dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq); + config->dynamicLinker = getDynamicLinker(args); + config->ehFrameHdr = + args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); + config->emitLLVM = args.hasArg(OPT_plugin_opt_emit_llvm, false); + config->emitRelocs = args.hasArg(OPT_emit_relocs); + config->callGraphProfileSort = args.hasFlag( OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true); - Config->EnableNewDtags = - Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); - Config->Entry = Args.getLastArgValue(OPT_entry); - Config->ExecuteOnly = - Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false); - Config->ExportDynamic = - Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); - Config->FilterList = args::getStrings(Args, OPT_filter); - Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); - Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419); - Config->ForceBTI = Args.hasArg(OPT_force_bti); - Config->RequireCET = Args.hasArg(OPT_require_cet); - Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); - Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true); - Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); - Config->ICF = getICF(Args); - Config->IgnoreDataAddressEquality = - Args.hasArg(OPT_ignore_data_address_equality); - Config->IgnoreFunctionAddressEquality = - Args.hasArg(OPT_ignore_function_address_equality); - Config->Init = Args.getLastArgValue(OPT_init, "_init"); - Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline); - Config->LTOCSProfileGenerate = Args.hasArg(OPT_lto_cs_profile_generate); - Config->LTOCSProfileFile = Args.getLastArgValue(OPT_lto_cs_profile_file); - Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager); - Config->LTONewPassManager = Args.hasArg(OPT_lto_new_pass_manager); - Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes); - Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); - Config->LTOObjPath = Args.getLastArgValue(OPT_plugin_opt_obj_path_eq); - Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); - Config->LTOSampleProfile = Args.getLastArgValue(OPT_lto_sample_profile); - Config->MapFile = Args.getLastArgValue(OPT_Map); - Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0); - Config->MergeArmExidx = - Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true); - Config->Nmagic = Args.hasFlag(OPT_nmagic, OPT_no_nmagic, false); - Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); - Config->Nostdlib = Args.hasArg(OPT_nostdlib); - Config->OFormatBinary = isOutputFormatBinary(Args); - Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false); - Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename); - Config->OptRemarksPasses = Args.getLastArgValue(OPT_opt_remarks_passes); - Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness); - Config->OptRemarksFormat = Args.getLastArgValue(OPT_opt_remarks_format); - Config->Optimize = args::getInteger(Args, OPT_O, 1); - Config->OrphanHandling = getOrphanHandling(Args); - Config->OutputFile = Args.getLastArgValue(OPT_o); - Config->PacPlt = Args.hasArg(OPT_pac_plt); - Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false); - Config->PrintIcfSections = - Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); - Config->PrintGcSections = - Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); - Config->PrintSymbolOrder = - Args.getLastArgValue(OPT_print_symbol_order); - Config->Rpath = getRpath(Args); - Config->Relocatable = Args.hasArg(OPT_relocatable); - Config->SaveTemps = Args.hasArg(OPT_save_temps); - Config->SearchPaths = args::getStrings(Args, OPT_library_path); - Config->SectionStartMap = getSectionStartMap(Args); - Config->Shared = Args.hasArg(OPT_shared); - Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); - Config->SoName = Args.getLastArgValue(OPT_soname); - Config->SortSection = getSortSection(Args); - Config->SplitStackAdjustSize = args::getInteger(Args, OPT_split_stack_adjust_size, 16384); - Config->Strip = getStrip(Args); - Config->Sysroot = Args.getLastArgValue(OPT_sysroot); - Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false); - Config->Target2 = getTarget2(Args); - Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir); - Config->ThinLTOCachePolicy = CHECK( - parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)), + config->enableNewDtags = + args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); + config->entry = args.getLastArgValue(OPT_entry); + config->executeOnly = + args.hasFlag(OPT_execute_only, OPT_no_execute_only, false); + config->exportDynamic = + args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); + config->filterList = args::getStrings(args, OPT_filter); + config->fini = args.getLastArgValue(OPT_fini, "_fini"); + config->fixCortexA53Errata843419 = args.hasArg(OPT_fix_cortex_a53_843419); + config->forceBTI = args.hasArg(OPT_force_bti); + config->requireCET = args.hasArg(OPT_require_cet); + config->gcSections = args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); + config->gnuUnique = args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true); + config->gdbIndex = args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); + config->icf = getICF(args); + config->ignoreDataAddressEquality = + args.hasArg(OPT_ignore_data_address_equality); + config->ignoreFunctionAddressEquality = + args.hasArg(OPT_ignore_function_address_equality); + config->init = args.getLastArgValue(OPT_init, "_init"); + config->ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline); + config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate); + config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file); + config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager); + config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager); + config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes); + config->ltoo = args::getInteger(args, OPT_lto_O, 2); + config->ltoObjPath = args.getLastArgValue(OPT_plugin_opt_obj_path_eq); + config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); + config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile); + config->mapFile = args.getLastArgValue(OPT_Map); + config->mipsGotSize = args::getInteger(args, OPT_mips_got_size, 0xfff0); + config->mergeArmExidx = + args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true); + config->nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false); + config->noinhibitExec = args.hasArg(OPT_noinhibit_exec); + config->nostdlib = args.hasArg(OPT_nostdlib); + config->oFormatBinary = isOutputFormatBinary(args); + config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false); + config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename); + config->optRemarksPasses = args.getLastArgValue(OPT_opt_remarks_passes); + config->optRemarksWithHotness = args.hasArg(OPT_opt_remarks_with_hotness); + config->optRemarksFormat = args.getLastArgValue(OPT_opt_remarks_format); + config->optimize = args::getInteger(args, OPT_O, 1); + config->orphanHandling = getOrphanHandling(args); + config->outputFile = args.getLastArgValue(OPT_o); + config->pacPlt = args.hasArg(OPT_pac_plt); + config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); + config->printIcfSections = + args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); + config->printGcSections = + args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); + config->printSymbolOrder = + args.getLastArgValue(OPT_print_symbol_order); + config->rpath = getRpath(args); + config->relocatable = args.hasArg(OPT_relocatable); + config->saveTemps = args.hasArg(OPT_save_temps); + config->searchPaths = args::getStrings(args, OPT_library_path); + config->sectionStartMap = getSectionStartMap(args); + config->shared = args.hasArg(OPT_shared); + config->singleRoRx = args.hasArg(OPT_no_rosegment); + config->soName = args.getLastArgValue(OPT_soname); + config->sortSection = getSortSection(args); + config->splitStackAdjustSize = args::getInteger(args, OPT_split_stack_adjust_size, 16384); + config->strip = getStrip(args); + config->sysroot = args.getLastArgValue(OPT_sysroot); + config->target1Rel = args.hasFlag(OPT_target1_rel, OPT_target1_abs, false); + config->target2 = getTarget2(args); + config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir); + config->thinLTOCachePolicy = CHECK( + parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)), "--thinlto-cache-policy: invalid cache policy"); - Config->ThinLTOEmitImportsFiles = - Args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files); - Config->ThinLTOIndexOnly = Args.hasArg(OPT_plugin_opt_thinlto_index_only) || - Args.hasArg(OPT_plugin_opt_thinlto_index_only_eq); - Config->ThinLTOIndexOnlyArg = - Args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq); - Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u); - Config->ThinLTOObjectSuffixReplace = - getOldNewOptions(Args, OPT_plugin_opt_thinlto_object_suffix_replace_eq); - Config->ThinLTOPrefixReplace = - getOldNewOptions(Args, OPT_plugin_opt_thinlto_prefix_replace_eq); - Config->Trace = Args.hasArg(OPT_trace); - Config->Undefined = args::getStrings(Args, OPT_undefined); - Config->UndefinedVersion = - Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true); - Config->UseAndroidRelrTags = Args.hasFlag( + config->thinLTOEmitImportsFiles = + args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files); + config->thinLTOIndexOnly = args.hasArg(OPT_plugin_opt_thinlto_index_only) || + args.hasArg(OPT_plugin_opt_thinlto_index_only_eq); + config->thinLTOIndexOnlyArg = + args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq); + config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u); + config->thinLTOObjectSuffixReplace = + getOldNewOptions(args, OPT_plugin_opt_thinlto_object_suffix_replace_eq); + config->thinLTOPrefixReplace = + getOldNewOptions(args, OPT_plugin_opt_thinlto_prefix_replace_eq); + config->trace = args.hasArg(OPT_trace); + config->undefined = args::getStrings(args, OPT_undefined); + config->undefinedVersion = + args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true); + config->useAndroidRelrTags = args.hasFlag( OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false); - Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); - Config->WarnBackrefs = - Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false); - Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false); - Config->WarnIfuncTextrel = - Args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false); - Config->WarnSymbolOrdering = - Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true); - Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true); - Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true); - Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false); - Config->ZGlobal = hasZOption(Args, "global"); - Config->ZHazardplt = hasZOption(Args, "hazardplt"); - Config->ZIfuncNoplt = hasZOption(Args, "ifunc-noplt"); - Config->ZInitfirst = hasZOption(Args, "initfirst"); - Config->ZInterpose = hasZOption(Args, "interpose"); - Config->ZKeepTextSectionPrefix = getZFlag( - Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false); - Config->ZNodefaultlib = hasZOption(Args, "nodefaultlib"); - Config->ZNodelete = hasZOption(Args, "nodelete"); - Config->ZNodlopen = hasZOption(Args, "nodlopen"); - Config->ZNow = getZFlag(Args, "now", "lazy", false); - Config->ZOrigin = hasZOption(Args, "origin"); - Config->ZRelro = getZFlag(Args, "relro", "norelro", true); - Config->ZRetpolineplt = hasZOption(Args, "retpolineplt"); - Config->ZRodynamic = hasZOption(Args, "rodynamic"); - Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0); - Config->ZText = getZFlag(Args, "text", "notext", true); - Config->ZWxneeded = hasZOption(Args, "wxneeded"); + config->unresolvedSymbols = getUnresolvedSymbolPolicy(args); + config->warnBackrefs = + args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false); + config->warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false); + config->warnIfuncTextrel = + args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false); + config->warnSymbolOrdering = + args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true); + config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true); + config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true); + config->zExecstack = getZFlag(args, "execstack", "noexecstack", false); + config->zGlobal = hasZOption(args, "global"); + config->zHazardplt = hasZOption(args, "hazardplt"); + config->zIfuncNoplt = hasZOption(args, "ifunc-noplt"); + config->zInitfirst = hasZOption(args, "initfirst"); + config->zInterpose = hasZOption(args, "interpose"); + config->zKeepTextSectionPrefix = getZFlag( + args, "keep-text-section-prefix", "nokeep-text-section-prefix", false); + config->zNodefaultlib = hasZOption(args, "nodefaultlib"); + config->zNodelete = hasZOption(args, "nodelete"); + config->zNodlopen = hasZOption(args, "nodlopen"); + config->zNow = getZFlag(args, "now", "lazy", false); + config->zOrigin = hasZOption(args, "origin"); + config->zRelro = getZFlag(args, "relro", "norelro", true); + config->zRetpolineplt = hasZOption(args, "retpolineplt"); + config->zRodynamic = hasZOption(args, "rodynamic"); + config->zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0); + config->zText = getZFlag(args, "text", "notext", true); + config->zWxneeded = hasZOption(args, "wxneeded"); // Parse LTO options. - if (auto *Arg = Args.getLastArg(OPT_plugin_opt_mcpu_eq)) - parseClangOption(Saver.save("-mcpu=" + StringRef(Arg->getValue())), - Arg->getSpelling()); + if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq)) + parseClangOption(Saver.save("-mcpu=" + StringRef(arg->getValue())), + arg->getSpelling()); - for (auto *Arg : Args.filtered(OPT_plugin_opt)) - parseClangOption(Arg->getValue(), Arg->getSpelling()); + for (auto *arg : args.filtered(OPT_plugin_opt)) + parseClangOption(arg->getValue(), arg->getSpelling()); // Parse -mllvm options. - for (auto *Arg : Args.filtered(OPT_mllvm)) - parseClangOption(Arg->getValue(), Arg->getSpelling()); + for (auto *arg : args.filtered(OPT_mllvm)) + parseClangOption(arg->getValue(), arg->getSpelling()); - if (Config->LTOO > 3) - error("invalid optimization level for LTO: " + Twine(Config->LTOO)); - if (Config->LTOPartitions == 0) + if (config->ltoo > 3) + error("invalid optimization level for LTO: " + Twine(config->ltoo)); + if (config->ltoPartitions == 0) error("--lto-partitions: number of threads must be > 0"); - if (Config->ThinLTOJobs == 0) + if (config->thinLTOJobs == 0) error("--thinlto-jobs: number of threads must be > 0"); - if (Config->SplitStackAdjustSize < 0) + if (config->splitStackAdjustSize < 0) error("--split-stack-adjust-size: size must be >= 0"); // Parse ELF{32,64}{LE,BE} and CPU type. - if (auto *Arg = Args.getLastArg(OPT_m)) { - StringRef S = Arg->getValue(); - std::tie(Config->EKind, Config->EMachine, Config->OSABI) = - parseEmulation(S); - Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32"); - Config->Emulation = S; + if (auto *arg = args.getLastArg(OPT_m)) { + StringRef s = arg->getValue(); + std::tie(config->ekind, config->emachine, config->osabi) = + parseEmulation(s); + config->mipsN32Abi = (s == "elf32btsmipn32" || s == "elf32ltsmipn32"); + config->emulation = s; } // Parse -hash-style={sysv,gnu,both}. - if (auto *Arg = Args.getLastArg(OPT_hash_style)) { - StringRef S = Arg->getValue(); - if (S == "sysv") - Config->SysvHash = true; - else if (S == "gnu") - Config->GnuHash = true; - else if (S == "both") - Config->SysvHash = Config->GnuHash = true; + if (auto *arg = args.getLastArg(OPT_hash_style)) { + StringRef s = arg->getValue(); + if (s == "sysv") + config->sysvHash = true; + else if (s == "gnu") + config->gnuHash = true; + else if (s == "both") + config->sysvHash = config->gnuHash = true; else - error("unknown -hash-style: " + S); + error("unknown -hash-style: " + s); } - if (Args.hasArg(OPT_print_map)) - Config->MapFile = "-"; + if (args.hasArg(OPT_print_map)) + config->mapFile = "-"; // Page alignment can be disabled by the -n (--nmagic) and -N (--omagic). // As PT_GNU_RELRO relies on Paging, do not create it when we have disabled // it. - if (Config->Nmagic || Config->Omagic) - Config->ZRelro = false; + if (config->nmagic || config->omagic) + config->zRelro = false; - std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args); + std::tie(config->buildId, config->buildIdVector) = getBuildId(args); - std::tie(Config->AndroidPackDynRelocs, Config->RelrPackDynRelocs) = - getPackDynRelocs(Args); + std::tie(config->androidPackDynRelocs, config->relrPackDynRelocs) = + getPackDynRelocs(args); - if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)){ - if (Args.hasArg(OPT_call_graph_ordering_file)) + if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){ + if (args.hasArg(OPT_call_graph_ordering_file)) error("--symbol-ordering-file and --call-graph-order-file " "may not be used together"); - if (Optional Buffer = readFile(Arg->getValue())){ - Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer); + if (Optional buffer = readFile(arg->getValue())){ + config->symbolOrderingFile = getSymbolOrderingFile(*buffer); // Also need to disable CallGraphProfileSort to prevent // LLD order symbols with CGProfile - Config->CallGraphProfileSort = false; + config->callGraphProfileSort = false; } } // If --retain-symbol-file is used, we'll keep only the symbols listed in // the file and discard all others. - if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) { - Config->DefaultSymbolVersion = VER_NDX_LOCAL; - if (Optional Buffer = readFile(Arg->getValue())) - for (StringRef S : args::getLines(*Buffer)) - Config->VersionScriptGlobals.push_back( - {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); + if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) { + config->defaultSymbolVersion = VER_NDX_LOCAL; + if (Optional buffer = readFile(arg->getValue())) + for (StringRef s : args::getLines(*buffer)) + config->versionScriptGlobals.push_back( + {s, /*IsExternCpp*/ false, /*HasWildcard*/ false}); } - bool HasExportDynamic = - Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); + bool hasExportDynamic = + args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); // Parses -dynamic-list and -export-dynamic-symbol. They make some // symbols private. Note that -export-dynamic takes precedence over them // as it says all symbols should be exported. - if (!HasExportDynamic) { - for (auto *Arg : Args.filtered(OPT_dynamic_list)) - if (Optional Buffer = readFile(Arg->getValue())) - readDynamicList(*Buffer); - - for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) - Config->DynamicList.push_back( - {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); + if (!hasExportDynamic) { + for (auto *arg : args.filtered(OPT_dynamic_list)) + if (Optional buffer = readFile(arg->getValue())) + readDynamicList(*buffer); + + for (auto *arg : args.filtered(OPT_export_dynamic_symbol)) + config->dynamicList.push_back( + {arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); } // If --export-dynamic-symbol=foo is given and symbol foo is defined in // an object file in an archive file, that object file should be pulled // out and linked. (It doesn't have to behave like that from technical // point of view, but this is needed for compatibility with GNU.) - for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) - Config->Undefined.push_back(Arg->getValue()); + for (auto *arg : args.filtered(OPT_export_dynamic_symbol)) + config->undefined.push_back(arg->getValue()); - for (auto *Arg : Args.filtered(OPT_version_script)) - if (Optional Path = searchScript(Arg->getValue())) { - if (Optional Buffer = readFile(*Path)) - readVersionScript(*Buffer); + for (auto *arg : args.filtered(OPT_version_script)) + if (Optional path = searchScript(arg->getValue())) { + if (Optional buffer = readFile(*path)) + readVersionScript(*buffer); } else { - error(Twine("cannot find version script ") + Arg->getValue()); + error(Twine("cannot find version script ") + arg->getValue()); } } @@ -1053,18 +1053,18 @@ // command line options, but computed based on other Config values. // This function initialize such members. See Config.h for the details // of these values. -static void setConfigs(opt::InputArgList &Args) { - ELFKind K = Config->EKind; - uint16_t M = Config->EMachine; - - Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs); - Config->Is64 = (K == ELF64LEKind || K == ELF64BEKind); - Config->IsLE = (K == ELF32LEKind || K == ELF64LEKind); - Config->Endianness = Config->IsLE ? endianness::little : endianness::big; - Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS); - Config->Pic = Config->Pie || Config->Shared; - Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic); - Config->Wordsize = Config->Is64 ? 8 : 4; +static void setConfigs(opt::InputArgList &args) { + ELFKind k = config->ekind; + uint16_t m = config->emachine; + + config->copyRelocs = (config->relocatable || config->emitRelocs); + config->is64 = (k == ELF64LEKind || k == ELF64BEKind); + config->isLE = (k == ELF32LEKind || k == ELF64LEKind); + config->endianness = config->isLE ? endianness::little : endianness::big; + config->isMips64EL = (k == ELF64LEKind && m == EM_MIPS); + config->isPic = config->pie || config->shared; + config->picThunk = args.hasArg(OPT_pic_veneer, config->isPic); + config->wordsize = config->is64 ? 8 : 4; // ELF defines two different ways to store relocation addends as shown below: // @@ -1079,150 +1079,150 @@ // You cannot choose which one, Rel or Rela, you want to use. Instead each // ABI defines which one you need to use. The following expression expresses // that. - Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_HEXAGON || - M == EM_PPC || M == EM_PPC64 || M == EM_RISCV || - M == EM_X86_64; + config->isRela = m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON || + m == EM_PPC || m == EM_PPC64 || m == EM_RISCV || + m == EM_X86_64; // If the output uses REL relocations we must store the dynamic relocation // addends to the output sections. We also store addends for RELA relocations // if --apply-dynamic-relocs is used. // We default to not writing the addends when using RELA relocations since // any standard conforming tool can find it in r_addend. - Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs, + config->writeAddends = args.hasFlag(OPT_apply_dynamic_relocs, OPT_no_apply_dynamic_relocs, false) || - !Config->IsRela; + !config->isRela; - Config->TocOptimize = - Args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, M == EM_PPC64); + config->tocOptimize = + args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64); } // Returns a value of "-format" option. -static bool isFormatBinary(StringRef S) { - if (S == "binary") +static bool isFormatBinary(StringRef s) { + if (s == "binary") return true; - if (S == "elf" || S == "default") + if (s == "elf" || s == "default") return false; - error("unknown -format value: " + S + + error("unknown -format value: " + s + " (supported formats: elf, default, binary)"); return false; } -void LinkerDriver::createFiles(opt::InputArgList &Args) { +void LinkerDriver::createFiles(opt::InputArgList &args) { // For --{push,pop}-state. - std::vector> Stack; + std::vector> stack; // Iterate over argv to process input files and positional arguments. - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_library: - addLibrary(Arg->getValue()); + addLibrary(arg->getValue()); break; case OPT_INPUT: - addFile(Arg->getValue(), /*WithLOption=*/false); + addFile(arg->getValue(), /*WithLOption=*/false); break; case OPT_defsym: { - StringRef From; - StringRef To; - std::tie(From, To) = StringRef(Arg->getValue()).split('='); - if (From.empty() || To.empty()) - error("-defsym: syntax error: " + StringRef(Arg->getValue())); + StringRef from; + StringRef to; + std::tie(from, to) = StringRef(arg->getValue()).split('='); + if (from.empty() || to.empty()) + error("-defsym: syntax error: " + StringRef(arg->getValue())); else - readDefsym(From, MemoryBufferRef(To, "-defsym")); + readDefsym(from, MemoryBufferRef(to, "-defsym")); break; } case OPT_script: - if (Optional Path = searchScript(Arg->getValue())) { - if (Optional MB = readFile(*Path)) - readLinkerScript(*MB); + if (Optional path = searchScript(arg->getValue())) { + if (Optional mb = readFile(*path)) + readLinkerScript(*mb); break; } - error(Twine("cannot find linker script ") + Arg->getValue()); + error(Twine("cannot find linker script ") + arg->getValue()); break; case OPT_as_needed: - Config->AsNeeded = true; + config->asNeeded = true; break; case OPT_format: - Config->FormatBinary = isFormatBinary(Arg->getValue()); + config->formatBinary = isFormatBinary(arg->getValue()); break; case OPT_no_as_needed: - Config->AsNeeded = false; + config->asNeeded = false; break; case OPT_Bstatic: case OPT_omagic: case OPT_nmagic: - Config->Static = true; + config->isStatic = true; break; case OPT_Bdynamic: - Config->Static = false; + config->isStatic = false; break; case OPT_whole_archive: - InWholeArchive = true; + inWholeArchive = true; break; case OPT_no_whole_archive: - InWholeArchive = false; + inWholeArchive = false; break; case OPT_just_symbols: - if (Optional MB = readFile(Arg->getValue())) { - Files.push_back(createObjectFile(*MB)); - Files.back()->JustSymbols = true; + if (Optional mb = readFile(arg->getValue())) { + files.push_back(createObjectFile(*mb)); + files.back()->justSymbols = true; } break; case OPT_start_group: - if (InputFile::IsInGroup) + if (InputFile::isInGroup) error("nested --start-group"); - InputFile::IsInGroup = true; + InputFile::isInGroup = true; break; case OPT_end_group: - if (!InputFile::IsInGroup) + if (!InputFile::isInGroup) error("stray --end-group"); - InputFile::IsInGroup = false; - ++InputFile::NextGroupId; + InputFile::isInGroup = false; + ++InputFile::nextGroupId; break; case OPT_start_lib: - if (InLib) + if (inLib) error("nested --start-lib"); - if (InputFile::IsInGroup) + if (InputFile::isInGroup) error("may not nest --start-lib in --start-group"); - InLib = true; - InputFile::IsInGroup = true; + inLib = true; + InputFile::isInGroup = true; break; case OPT_end_lib: - if (!InLib) + if (!inLib) error("stray --end-lib"); - InLib = false; - InputFile::IsInGroup = false; - ++InputFile::NextGroupId; + inLib = false; + InputFile::isInGroup = false; + ++InputFile::nextGroupId; break; case OPT_push_state: - Stack.emplace_back(Config->AsNeeded, Config->Static, InWholeArchive); + stack.emplace_back(config->asNeeded, config->isStatic, inWholeArchive); break; case OPT_pop_state: - if (Stack.empty()) { + if (stack.empty()) { error("unbalanced --push-state/--pop-state"); break; } - std::tie(Config->AsNeeded, Config->Static, InWholeArchive) = Stack.back(); - Stack.pop_back(); + std::tie(config->asNeeded, config->isStatic, inWholeArchive) = stack.back(); + stack.pop_back(); break; } } - if (Files.empty() && errorCount() == 0) + if (files.empty() && errorCount() == 0) error("no input files"); } // If -m was not given, infer it from object files. void LinkerDriver::inferMachineType() { - if (Config->EKind != ELFNoneKind) + if (config->ekind != ELFNoneKind) return; - for (InputFile *F : Files) { - if (F->EKind == ELFNoneKind) + for (InputFile *f : files) { + if (f->ekind == ELFNoneKind) continue; - Config->EKind = F->EKind; - Config->EMachine = F->EMachine; - Config->OSABI = F->OSABI; - Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F); + config->ekind = f->ekind; + config->emachine = f->emachine; + config->osabi = f->osabi; + config->mipsN32Abi = config->emachine == EM_MIPS && isMipsN32Abi(f); return; } error("target emulation unknown: -m or at least one .o file required"); @@ -1230,72 +1230,72 @@ // Parse -z max-page-size=. The default value is defined by // each target. -static uint64_t getMaxPageSize(opt::InputArgList &Args) { - uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size", - Target->DefaultMaxPageSize); - if (!isPowerOf2_64(Val)) +static uint64_t getMaxPageSize(opt::InputArgList &args) { + uint64_t val = args::getZOptionValue(args, OPT_z, "max-page-size", + target->defaultMaxPageSize); + if (!isPowerOf2_64(val)) error("max-page-size: value isn't a power of 2"); - if (Config->Nmagic || Config->Omagic) { - if (Val != Target->DefaultMaxPageSize) + if (config->nmagic || config->omagic) { + if (val != target->defaultMaxPageSize) warn("-z max-page-size set, but paging disabled by omagic or nmagic"); return 1; } - return Val; + return val; } // Parse -z common-page-size=. The default value is defined by // each target. -static uint64_t getCommonPageSize(opt::InputArgList &Args) { - uint64_t Val = args::getZOptionValue(Args, OPT_z, "common-page-size", - Target->DefaultCommonPageSize); - if (!isPowerOf2_64(Val)) +static uint64_t getCommonPageSize(opt::InputArgList &args) { + uint64_t val = args::getZOptionValue(args, OPT_z, "common-page-size", + target->defaultCommonPageSize); + if (!isPowerOf2_64(val)) error("common-page-size: value isn't a power of 2"); - if (Config->Nmagic || Config->Omagic) { - if (Val != Target->DefaultCommonPageSize) + if (config->nmagic || config->omagic) { + if (val != target->defaultCommonPageSize) warn("-z common-page-size set, but paging disabled by omagic or nmagic"); return 1; } // CommonPageSize can't be larger than MaxPageSize. - if (Val > Config->MaxPageSize) - Val = Config->MaxPageSize; - return Val; + if (val > config->maxPageSize) + val = config->maxPageSize; + return val; } // Parses -image-base option. -static Optional getImageBase(opt::InputArgList &Args) { +static Optional getImageBase(opt::InputArgList &args) { // Because we are using "Config->MaxPageSize" here, this function has to be // called after the variable is initialized. - auto *Arg = Args.getLastArg(OPT_image_base); - if (!Arg) + auto *arg = args.getLastArg(OPT_image_base); + if (!arg) return None; - StringRef S = Arg->getValue(); - uint64_t V; - if (!to_integer(S, V)) { - error("-image-base: number expected, but got " + S); + StringRef s = arg->getValue(); + uint64_t v; + if (!to_integer(s, v)) { + error("-image-base: number expected, but got " + s); return 0; } - if ((V % Config->MaxPageSize) != 0) - warn("-image-base: address isn't multiple of page size: " + S); - return V; + if ((v % config->maxPageSize) != 0) + warn("-image-base: address isn't multiple of page size: " + s); + return v; } // Parses `--exclude-libs=lib,lib,...`. // The library names may be delimited by commas or colons. -static DenseSet getExcludeLibs(opt::InputArgList &Args) { - DenseSet Ret; - for (auto *Arg : Args.filtered(OPT_exclude_libs)) { - StringRef S = Arg->getValue(); +static DenseSet getExcludeLibs(opt::InputArgList &args) { + DenseSet ret; + for (auto *arg : args.filtered(OPT_exclude_libs)) { + StringRef s = arg->getValue(); for (;;) { - size_t Pos = S.find_first_of(",:"); - if (Pos == StringRef::npos) + size_t pos = s.find_first_of(",:"); + if (pos == StringRef::npos) break; - Ret.insert(S.substr(0, Pos)); - S = S.substr(Pos + 1); + ret.insert(s.substr(0, pos)); + s = s.substr(pos + 1); } - Ret.insert(S); + ret.insert(s); } - return Ret; + return ret; } // Handles the -exclude-libs option. If a static library file is specified @@ -1304,71 +1304,71 @@ // A special library name "ALL" means all archive files. // // This is not a popular option, but some programs such as bionic libc use it. -static void excludeLibs(opt::InputArgList &Args) { - DenseSet Libs = getExcludeLibs(Args); - bool All = Libs.count("ALL"); - - auto Visit = [&](InputFile *File) { - if (!File->ArchiveName.empty()) - if (All || Libs.count(path::filename(File->ArchiveName))) - for (Symbol *Sym : File->getSymbols()) - if (!Sym->isLocal() && Sym->File == File) - Sym->VersionId = VER_NDX_LOCAL; +static void excludeLibs(opt::InputArgList &args) { + DenseSet libs = getExcludeLibs(args); + bool all = libs.count("ALL"); + + auto visit = [&](InputFile *file) { + if (!file->archiveName.empty()) + if (all || libs.count(path::filename(file->archiveName))) + for (Symbol *sym : file->getSymbols()) + if (!sym->isLocal() && sym->file == file) + sym->versionId = VER_NDX_LOCAL; }; - for (InputFile *File : ObjectFiles) - Visit(File); + for (InputFile *file : objectFiles) + visit(file); - for (BitcodeFile *File : BitcodeFiles) - Visit(File); + for (BitcodeFile *file : bitcodeFiles) + visit(file); } // Force Sym to be entered in the output. Used for -u or equivalent. -static void handleUndefined(Symbol *Sym) { +static void handleUndefined(Symbol *sym) { // Since a symbol may not be used inside the program, LTO may // eliminate it. Mark the symbol as "used" to prevent it. - Sym->IsUsedInRegularObj = true; + sym->isUsedInRegularObj = true; - if (Sym->isLazy()) - Sym->fetch(); + if (sym->isLazy()) + sym->fetch(); } // As an extention to GNU linkers, lld supports a variant of `-u` // which accepts wildcard patterns. All symbols that match a given // pattern are handled as if they were given by `-u`. -static void handleUndefinedGlob(StringRef Arg) { - Expected Pat = GlobPattern::create(Arg); - if (!Pat) { - error("--undefined-glob: " + toString(Pat.takeError())); +static void handleUndefinedGlob(StringRef arg) { + Expected pat = GlobPattern::create(arg); + if (!pat) { + error("--undefined-glob: " + toString(pat.takeError())); return; } - std::vector Syms; - Symtab->forEachSymbol([&](Symbol *Sym) { + std::vector syms; + symtab->forEachSymbol([&](Symbol *sym) { // Calling Sym->fetch() from here is not safe because it may // add new symbols to the symbol table, invalidating the // current iterator. So we just keep a note. - if (Pat->match(Sym->getName())) - Syms.push_back(Sym); + if (pat->match(sym->getName())) + syms.push_back(sym); }); - for (Symbol *Sym : Syms) - handleUndefined(Sym); + for (Symbol *sym : syms) + handleUndefined(sym); } -static void handleLibcall(StringRef Name) { - Symbol *Sym = Symtab->find(Name); - if (!Sym || !Sym->isLazy()) +static void handleLibcall(StringRef name) { + Symbol *sym = symtab->find(name); + if (!sym || !sym->isLazy()) return; - MemoryBufferRef MB; - if (auto *LO = dyn_cast(Sym)) - MB = LO->File->MB; + MemoryBufferRef mb; + if (auto *lo = dyn_cast(sym)) + mb = lo->file->mb; else - MB = cast(Sym)->getMemberBuffer(); + mb = cast(sym)->getMemberBuffer(); - if (isBitcode(MB)) - Sym->fetch(); + if (isBitcode(mb)) + sym->fetch(); } // Replaces common symbols with defined symbols reside in .bss sections. @@ -1376,17 +1376,17 @@ // result, the passes after the symbol resolution won't see any // symbols of type CommonSymbol. static void replaceCommonSymbols() { - Symtab->forEachSymbol([](Symbol *Sym) { - auto *S = dyn_cast(Sym); - if (!S) + symtab->forEachSymbol([](Symbol *sym) { + auto *s = dyn_cast(sym); + if (!s) return; - auto *Bss = make("COMMON", S->Size, S->Alignment); - Bss->File = S->File; - Bss->markDead(); - InputSections.push_back(Bss); - S->replace(Defined{S->File, S->getName(), S->Binding, S->StOther, S->Type, - /*Value=*/0, S->Size, Bss}); + auto *bss = make("COMMON", s->size, s->alignment); + bss->file = s->file; + bss->markDead(); + inputSections.push_back(bss); + s->replace(Defined{s->file, s->getName(), s->binding, s->stOther, s->type, + /*Value=*/0, s->size, bss}); }); } @@ -1395,78 +1395,78 @@ // created from the DSO. Otherwise, they become dangling references // that point to a non-existent DSO. static void demoteSharedSymbols() { - Symtab->forEachSymbol([](Symbol *Sym) { - auto *S = dyn_cast(Sym); - if (!S || S->getFile().IsNeeded) + symtab->forEachSymbol([](Symbol *sym) { + auto *s = dyn_cast(sym); + if (!s || s->getFile().isNeeded) return; - bool Used = S->Used; - S->replace(Undefined{nullptr, S->getName(), STB_WEAK, S->StOther, S->Type}); - S->Used = Used; + bool used = s->used; + s->replace(Undefined{nullptr, s->getName(), STB_WEAK, s->stOther, s->type}); + s->used = used; }); } // The section referred to by S is considered address-significant. Set the // KeepUnique flag on the section if appropriate. -static void markAddrsig(Symbol *S) { - if (auto *D = dyn_cast_or_null(S)) - if (D->Section) +static void markAddrsig(Symbol *s) { + if (auto *d = dyn_cast_or_null(s)) + if (d->section) // We don't need to keep text sections unique under --icf=all even if they // are address-significant. - if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR)) - D->Section->KeepUnique = true; + if (config->icf == ICFLevel::Safe || !(d->section->flags & SHF_EXECINSTR)) + d->section->keepUnique = true; } // Record sections that define symbols mentioned in --keep-unique // and symbols referred to by address-significance tables. These sections are // ineligible for ICF. template -static void findKeepUniqueSections(opt::InputArgList &Args) { - for (auto *Arg : Args.filtered(OPT_keep_unique)) { - StringRef Name = Arg->getValue(); - auto *D = dyn_cast_or_null(Symtab->find(Name)); - if (!D || !D->Section) { - warn("could not find symbol " + Name + " to keep unique"); +static void findKeepUniqueSections(opt::InputArgList &args) { + for (auto *arg : args.filtered(OPT_keep_unique)) { + StringRef name = arg->getValue(); + auto *d = dyn_cast_or_null(symtab->find(name)); + if (!d || !d->section) { + warn("could not find symbol " + name + " to keep unique"); continue; } - D->Section->KeepUnique = true; + d->section->keepUnique = true; } // --icf=all --ignore-data-address-equality means that we can ignore // the dynsym and address-significance tables entirely. - if (Config->ICF == ICFLevel::All && Config->IgnoreDataAddressEquality) + if (config->icf == ICFLevel::All && config->ignoreDataAddressEquality) return; // Symbols in the dynsym could be address-significant in other executables // or DSOs, so we conservatively mark them as address-significant. - Symtab->forEachSymbol([&](Symbol *Sym) { - if (Sym->includeInDynsym()) - markAddrsig(Sym); + symtab->forEachSymbol([&](Symbol *sym) { + if (sym->includeInDynsym()) + markAddrsig(sym); }); // Visit the address-significance table in each object file and mark each // referenced symbol as address-significant. - for (InputFile *F : ObjectFiles) { - auto *Obj = cast>(F); - ArrayRef Syms = Obj->getSymbols(); - if (Obj->AddrsigSec) { - ArrayRef Contents = - check(Obj->getObj().getSectionContents(Obj->AddrsigSec)); - const uint8_t *Cur = Contents.begin(); - while (Cur != Contents.end()) { - unsigned Size; - const char *Err; - uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); - if (Err) - fatal(toString(F) + ": could not decode addrsig section: " + Err); - markAddrsig(Syms[SymIndex]); - Cur += Size; + for (InputFile *f : objectFiles) { + auto *obj = cast>(f); + ArrayRef syms = obj->getSymbols(); + if (obj->addrsigSec) { + ArrayRef contents = + check(obj->getObj().getSectionContents(obj->addrsigSec)); + const uint8_t *cur = contents.begin(); + while (cur != contents.end()) { + unsigned size; + const char *err; + uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err); + if (err) + fatal(toString(f) + ": could not decode addrsig section: " + err); + markAddrsig(syms[symIndex]); + cur += size; } } else { // If an object file does not have an address-significance table, // conservatively mark all of its symbols as address-significant. - for (Symbol *S : Syms) - markAddrsig(S); + for (Symbol *s : syms) + markAddrsig(s); } } } @@ -1475,20 +1475,20 @@ // are used to control which partition a symbol is allocated to. See // https://lld.llvm.org/Partitions.html for more details on partitions. template -static void readSymbolPartitionSection(InputSectionBase *S) { +static void readSymbolPartitionSection(InputSectionBase *s) { // Read the relocation that refers to the partition's entry point symbol. - Symbol *Sym; - if (S->AreRelocsRela) - Sym = &S->getFile()->getRelocTargetSym(S->template relas()[0]); + Symbol *sym; + if (s->areRelocsRela) + sym = &s->getFile()->getRelocTargetSym(s->template relas()[0]); else - Sym = &S->getFile()->getRelocTargetSym(S->template rels()[0]); - if (!isa(Sym) || !Sym->includeInDynsym()) + sym = &s->getFile()->getRelocTargetSym(s->template rels()[0]); + if (!isa(sym) || !sym->includeInDynsym()) return; - StringRef PartName = reinterpret_cast(S->data().data()); - for (Partition &Part : Partitions) { - if (Part.Name == PartName) { - Sym->Partition = Part.getNumber(); + StringRef partName = reinterpret_cast(s->data().data()); + for (Partition &part : partitions) { + if (part.name == partName) { + sym->partition = part.getNumber(); return; } } @@ -1496,33 +1496,33 @@ // Forbid partitions from being used on incompatible targets, and forbid them // from being used together with various linker features that assume a single // set of output sections. - if (Script->HasSectionsCommand) - error(toString(S->File) + + if (script->hasSectionsCommand) + error(toString(s->file) + ": partitions cannot be used with the SECTIONS command"); - if (Script->hasPhdrsCommands()) - error(toString(S->File) + + if (script->hasPhdrsCommands()) + error(toString(s->file) + ": partitions cannot be used with the PHDRS command"); - if (!Config->SectionStartMap.empty()) - error(toString(S->File) + ": partitions cannot be used with " + if (!config->sectionStartMap.empty()) + error(toString(s->file) + ": partitions cannot be used with " "--section-start, -Ttext, -Tdata or -Tbss"); - if (Config->EMachine == EM_MIPS) - error(toString(S->File) + ": partitions cannot be used on this target"); + if (config->emachine == EM_MIPS) + error(toString(s->file) + ": partitions cannot be used on this target"); // Impose a limit of no more than 254 partitions. This limit comes from the // sizes of the Partition fields in InputSectionBase and Symbol, as well as // the amount of space devoted to the partition number in RankFlags. - if (Partitions.size() == 254) + if (partitions.size() == 254) fatal("may not have more than 254 partitions"); - Partitions.emplace_back(); - Partition &NewPart = Partitions.back(); - NewPart.Name = PartName; - Sym->Partition = NewPart.getNumber(); + partitions.emplace_back(); + Partition &newPart = partitions.back(); + newPart.name = partName; + sym->partition = newPart.getNumber(); } -static Symbol *addUndefined(StringRef Name) { - return Symtab->addSymbol( - Undefined{nullptr, Name, STB_GLOBAL, STV_DEFAULT, 0}); +static Symbol *addUndefined(StringRef name) { + return symtab->addSymbol( + Undefined{nullptr, name, STB_GLOBAL, STV_DEFAULT, 0}); } // This function is where all the optimizations of link-time @@ -1534,16 +1534,16 @@ // the compiler at once, it can do a whole-program optimization. template void LinkerDriver::compileBitcodeFiles() { // Compile bitcode files and replace bitcode symbols. - LTO.reset(new BitcodeCompiler); - for (BitcodeFile *File : BitcodeFiles) - LTO->add(*File); - - for (InputFile *File : LTO->compile()) { - auto *Obj = cast>(File); - Obj->parse(/*IgnoreComdats=*/true); - for (Symbol *Sym : Obj->getGlobalSymbols()) - Sym->parseSymbolVersion(); - ObjectFiles.push_back(File); + lto.reset(new BitcodeCompiler); + for (BitcodeFile *file : bitcodeFiles) + lto->add(*file); + + for (InputFile *file : lto->compile()) { + auto *obj = cast>(file); + obj->parse(/*IgnoreComdats=*/true); + for (Symbol *sym : obj->getGlobalSymbols()) + sym->parseSymbolVersion(); + objectFiles.push_back(file); } } @@ -1556,9 +1556,9 @@ // // This data structure is instantiated for each -wrap option. struct WrappedSymbol { - Symbol *Sym; - Symbol *Real; - Symbol *Wrap; + Symbol *sym; + Symbol *real; + Symbol *wrap; }; // Handles -wrap option. @@ -1566,33 +1566,33 @@ // This function instantiates wrapper symbols. At this point, they seem // like they are not being used at all, so we explicitly set some flags so // that LTO won't eliminate them. -static std::vector addWrappedSymbols(opt::InputArgList &Args) { - std::vector V; - DenseSet Seen; - - for (auto *Arg : Args.filtered(OPT_wrap)) { - StringRef Name = Arg->getValue(); - if (!Seen.insert(Name).second) +static std::vector addWrappedSymbols(opt::InputArgList &args) { + std::vector v; + DenseSet seen; + + for (auto *arg : args.filtered(OPT_wrap)) { + StringRef name = arg->getValue(); + if (!seen.insert(name).second) continue; - Symbol *Sym = Symtab->find(Name); - if (!Sym) + Symbol *sym = symtab->find(name); + if (!sym) continue; - Symbol *Real = addUndefined(Saver.save("__real_" + Name)); - Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); - V.push_back({Sym, Real, Wrap}); + Symbol *real = addUndefined(Saver.save("__real_" + name)); + Symbol *wrap = addUndefined(Saver.save("__wrap_" + name)); + v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten // because LTO doesn't know the final symbol contents after renaming. - Real->CanInline = false; - Sym->CanInline = false; + real->canInline = false; + sym->canInline = false; // Tell LTO not to eliminate these symbols. - Sym->IsUsedInRegularObj = true; - Wrap->IsUsedInRegularObj = true; + sym->isUsedInRegularObj = true; + wrap->isUsedInRegularObj = true; } - return V; + return v; } // Do renaming for -wrap by updating pointers to symbols. @@ -1600,24 +1600,24 @@ // When this function is executed, only InputFiles and symbol table // contain pointers to symbol objects. We visit them to replace pointers, // so that wrapped symbols are swapped as instructed by the command line. -static void wrapSymbols(ArrayRef Wrapped) { - DenseMap Map; - for (const WrappedSymbol &W : Wrapped) { - Map[W.Sym] = W.Wrap; - Map[W.Real] = W.Sym; +static void wrapSymbols(ArrayRef wrapped) { + DenseMap map; + for (const WrappedSymbol &w : wrapped) { + map[w.sym] = w.wrap; + map[w.real] = w.sym; } // Update pointers in input files. - parallelForEach(ObjectFiles, [&](InputFile *File) { - MutableArrayRef Syms = File->getMutableSymbols(); - for (size_t I = 0, E = Syms.size(); I != E; ++I) - if (Symbol *S = Map.lookup(Syms[I])) - Syms[I] = S; + parallelForEach(objectFiles, [&](InputFile *file) { + MutableArrayRef syms = file->getMutableSymbols(); + for (size_t i = 0, e = syms.size(); i != e; ++i) + if (Symbol *s = map.lookup(syms[i])) + syms[i] = s; }); // Update pointers in the symbol table. - for (const WrappedSymbol &W : Wrapped) - Symtab->wrap(W.Sym, W.Real, W.Wrap); + for (const WrappedSymbol &w : wrapped) + symtab->wrap(w.sym, w.real, w.wrap); } // To enable CET (x86's hardware-assited control flow enforcement), each @@ -1633,30 +1633,30 @@ // Note that the CET-aware PLT is not implemented yet. We do error // check only. template static uint32_t getAndFeatures() { - if (Config->EMachine != EM_386 && Config->EMachine != EM_X86_64 && - Config->EMachine != EM_AARCH64) + if (config->emachine != EM_386 && config->emachine != EM_X86_64 && + config->emachine != EM_AARCH64) return 0; - uint32_t Ret = -1; - for (InputFile *F : ObjectFiles) { - uint32_t Features = cast>(F)->AndFeatures; - if (Config->ForceBTI && !(Features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) { - warn(toString(F) + ": --force-bti: file does not have BTI property"); - Features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI; - } else if (!Features && Config->RequireCET) - error(toString(F) + ": --require-cet: file is not compatible with CET"); - Ret &= Features; + uint32_t ret = -1; + for (InputFile *f : objectFiles) { + uint32_t features = cast>(f)->andFeatures; + if (config->forceBTI && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) { + warn(toString(f) + ": --force-bti: file does not have BTI property"); + features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI; + } else if (!features && config->requireCET) + error(toString(f) + ": --require-cet: file is not compatible with CET"); + ret &= features; } // Force enable pointer authentication Plt, we don't warn in this case as // this does not require support in the object for correctness. - if (Config->PacPlt) - Ret |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; + if (config->pacPlt) + ret |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; - return Ret; + return ret; } -static const char *LibcallRoutineNames[] = { +static const char *libcallRoutineNames[] = { #define HANDLE_LIBCALL(code, name) name, #include "llvm/IR/RuntimeLibcalls.def" #undef HANDLE_LIBCALL @@ -1664,48 +1664,48 @@ // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. -template void LinkerDriver::link(opt::InputArgList &Args) { +template void LinkerDriver::link(opt::InputArgList &args) { // If a -hash-style option was not given, set to a default value, // which varies depending on the target. - if (!Args.hasArg(OPT_hash_style)) { - if (Config->EMachine == EM_MIPS) - Config->SysvHash = true; + if (!args.hasArg(OPT_hash_style)) { + if (config->emachine == EM_MIPS) + config->sysvHash = true; else - Config->SysvHash = Config->GnuHash = true; + config->sysvHash = config->gnuHash = true; } // Default output filename is "a.out" by the Unix tradition. - if (Config->OutputFile.empty()) - Config->OutputFile = "a.out"; + if (config->outputFile.empty()) + config->outputFile = "a.out"; // Fail early if the output file or map file is not writable. If a user has a // long link, e.g. due to a large LTO link, they do not wish to run it and // find that it failed because there was a mistake in their command-line. - if (auto E = tryCreateFile(Config->OutputFile)) - error("cannot open output file " + Config->OutputFile + ": " + E.message()); - if (auto E = tryCreateFile(Config->MapFile)) - error("cannot open map file " + Config->MapFile + ": " + E.message()); + if (auto e = tryCreateFile(config->outputFile)) + error("cannot open output file " + config->outputFile + ": " + e.message()); + if (auto e = tryCreateFile(config->mapFile)) + error("cannot open map file " + config->mapFile + ": " + e.message()); if (errorCount()) return; // Use default entry point name if no name was given via the command // line nor linker scripts. For some reason, MIPS entry point name is // different from others. - Config->WarnMissingEntry = - (!Config->Entry.empty() || (!Config->Shared && !Config->Relocatable)); - if (Config->Entry.empty() && !Config->Relocatable) - Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start"; + config->warnMissingEntry = + (!config->entry.empty() || (!config->shared && !config->relocatable)); + if (config->entry.empty() && !config->relocatable) + config->entry = (config->emachine == EM_MIPS) ? "__start" : "_start"; // Handle --trace-symbol. - for (auto *Arg : Args.filtered(OPT_trace_symbol)) - Symtab->insert(Arg->getValue())->Traced = true; + for (auto *arg : args.filtered(OPT_trace_symbol)) + symtab->insert(arg->getValue())->traced = true; // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. This process might // add files to the link, via autolinking, these files are always // appended to the Files vector. - for (size_t I = 0; I < Files.size(); ++I) - parseFile(Files[I]); + for (size_t i = 0; i < files.size(); ++i) + parseFile(files[i]); // Now that we have every file, we can decide if we will need a // dynamic symbol table. @@ -1713,26 +1713,26 @@ // producing a shared library. // We also need one if any shared libraries are used and for pie executables // (probably because the dynamic linker needs it). - Config->HasDynSymTab = - !SharedFiles.empty() || Config->Pic || Config->ExportDynamic; + config->hasDynSymTab = + !sharedFiles.empty() || config->isPic || config->exportDynamic; // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. - for (StringRef Name : Script->ReferencedSymbols) - addUndefined(Name); + for (StringRef name : script->referencedSymbols) + addUndefined(name); // Handle the `--undefined ` options. - for (StringRef Arg : Config->Undefined) - if (Symbol *Sym = Symtab->find(Arg)) - handleUndefined(Sym); + for (StringRef arg : config->undefined) + if (Symbol *sym = symtab->find(arg)) + handleUndefined(sym); // If an entry symbol is in a static archive, pull out that file now. - if (Symbol *Sym = Symtab->find(Config->Entry)) - handleUndefined(Sym); + if (Symbol *sym = symtab->find(config->entry)) + handleUndefined(sym); // Handle the `--undefined-glob ` options. - for (StringRef Pat : args::getStrings(Args, OPT_undefined_glob)) - handleUndefinedGlob(Pat); + for (StringRef pat : args::getStrings(args, OPT_undefined_glob)) + handleUndefinedGlob(pat); // If any of our inputs are bitcode files, the LTO code generator may create // references to certain library functions that might not be explicit in the @@ -1751,9 +1751,9 @@ // to, i.e. if the symbol's definition is in bitcode. Any other required // libcall symbols will be added to the link after LTO when we add the LTO // object file to the link. - if (!BitcodeFiles.empty()) - for (const char *S : LibcallRoutineNames) - handleLibcall(S); + if (!bitcodeFiles.empty()) + for (const char *s : libcallRoutineNames) + handleLibcall(s); // Return if there were name resolution errors. if (errorCount()) @@ -1761,27 +1761,27 @@ // Now when we read all script files, we want to finalize order of linker // script commands, which can be not yet final because of INSERT commands. - Script->processInsertCommands(); + script->processInsertCommands(); // We want to declare linker script's symbols early, // so that we can version them. // They also might be exported if referenced by DSOs. - Script->declareSymbols(); + script->declareSymbols(); // Handle the -exclude-libs option. - if (Args.hasArg(OPT_exclude_libs)) - excludeLibs(Args); + if (args.hasArg(OPT_exclude_libs)) + excludeLibs(args); // Create ElfHeader early. We need a dummy section in // addReservedSymbols to mark the created symbols as not absolute. - Out::ElfHeader = make("", 0, SHF_ALLOC); - Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr); + Out::elfHeader = make("", 0, SHF_ALLOC); + Out::elfHeader->size = sizeof(typename ELFT::Ehdr); // Create wrapped symbols for -wrap option. - std::vector Wrapped = addWrappedSymbols(Args); + std::vector wrapped = addWrappedSymbols(args); // We need to create some reserved symbols such as _end. Create them. - if (!Config->Relocatable) + if (!config->relocatable) addReservedSymbols(); // Apply version scripts. @@ -1789,8 +1789,8 @@ // For a relocatable output, version scripts don't make sense, and // parsing a symbol version string (e.g. dropping "@ver1" from a symbol // name "foo@ver1") rather do harm, so we don't call this if -r is given. - if (!Config->Relocatable) - Symtab->scanVersionScript(); + if (!config->relocatable) + symtab->scanVersionScript(); // Do link-time optimization if given files are LLVM bitcode files. // This compiles bitcode files into real object files. @@ -1804,83 +1804,83 @@ // If -thinlto-index-only is given, we should create only "index // files" and not object files. Index file creation is already done // in addCombinedLTOObject, so we are done if that's the case. - if (Config->ThinLTOIndexOnly) + if (config->thinLTOIndexOnly) return; // Likewise, --plugin-opt=emit-llvm is an option to make LTO create // an output file in bitcode and exit, so that you can just get a // combined bitcode file. - if (Config->EmitLLVM) + if (config->emitLLVM) return; // Apply symbol renames for -wrap. - if (!Wrapped.empty()) - wrapSymbols(Wrapped); + if (!wrapped.empty()) + wrapSymbols(wrapped); // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. - for (InputFile *F : ObjectFiles) - for (InputSectionBase *S : F->getSections()) - if (S && S != &InputSection::Discarded) - InputSections.push_back(S); - for (BinaryFile *F : BinaryFiles) - for (InputSectionBase *S : F->getSections()) - InputSections.push_back(cast(S)); - - llvm::erase_if(InputSections, [](InputSectionBase *S) { - if (S->Type == SHT_LLVM_SYMPART) { - readSymbolPartitionSection(S); + for (InputFile *f : objectFiles) + for (InputSectionBase *s : f->getSections()) + if (s && s != &InputSection::discarded) + inputSections.push_back(s); + for (BinaryFile *f : binaryFiles) + for (InputSectionBase *s : f->getSections()) + inputSections.push_back(cast(s)); + + llvm::erase_if(inputSections, [](InputSectionBase *s) { + if (s->type == SHT_LLVM_SYMPART) { + readSymbolPartitionSection(s); return true; } // We do not want to emit debug sections if --strip-all // or -strip-debug are given. - return Config->Strip != StripPolicy::None && - (S->Name.startswith(".debug") || S->Name.startswith(".zdebug")); + return config->strip != StripPolicy::None && + (s->name.startswith(".debug") || s->name.startswith(".zdebug")); }); // Now that the number of partitions is fixed, save a pointer to the main // partition. - Main = &Partitions[0]; + mainPart = &partitions[0]; // Read .note.gnu.property sections from input object files which // contain a hint to tweak linker's and loader's behaviors. - Config->AndFeatures = getAndFeatures(); + config->andFeatures = getAndFeatures(); // The Target instance handles target-specific stuff, such as applying // relocations or writing a PLT section. It also contains target-dependent // values such as a default image base address. - Target = getTarget(); + target = getTarget(); - Config->EFlags = Target->calcEFlags(); + config->eflags = target->calcEFlags(); // MaxPageSize (sometimes called abi page size) is the maximum page size that // the output can be run on. For example if the OS can use 4k or 64k page // sizes then MaxPageSize must be 64 for the output to be useable on both. // All important alignment decisions must use this value. - Config->MaxPageSize = getMaxPageSize(Args); + config->maxPageSize = getMaxPageSize(args); // CommonPageSize is the most common page size that the output will be run on. // For example if an OS can use 4k or 64k page sizes and 4k is more common // than 64k then CommonPageSize is set to 4k. CommonPageSize can be used for // optimizations such as DATA_SEGMENT_ALIGN in linker scripts. LLD's use of it // is limited to writing trap instructions on the last executable segment. - Config->CommonPageSize = getCommonPageSize(Args); + config->commonPageSize = getCommonPageSize(args); - Config->ImageBase = getImageBase(Args); + config->imageBase = getImageBase(args); - if (Config->EMachine == EM_ARM) { + if (config->emachine == EM_ARM) { // FIXME: These warnings can be removed when lld only uses these features // when the input objects have been compiled with an architecture that // supports them. - if (Config->ARMHasBlx == false) + if (config->armHasBlx == false) warn("lld uses blx instruction, no object with architecture supporting " "feature detected"); } // This adds a .comment section containing a version string. We have to add it // before mergeSections because the .comment section is a mergeable section. - if (!Config->Relocatable) - InputSections.push_back(createCommentSection()); + if (!config->relocatable) + inputSections.push_back(createCommentSection()); // Replace common symbols with regular symbols. replaceCommonSymbols(); @@ -1891,16 +1891,16 @@ markLive(); demoteSharedSymbols(); mergeSections(); - if (Config->ICF != ICFLevel::None) { - findKeepUniqueSections(Args); + if (config->icf != ICFLevel::None) { + findKeepUniqueSections(args); doIcf(); } // Read the callgraph now that we know what was gced or icfed - if (Config->CallGraphProfileSort) { - if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file)) - if (Optional Buffer = readFile(Arg->getValue())) - readCallGraph(*Buffer); + if (config->callGraphProfileSort) { + if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file)) + if (Optional buffer = readFile(arg->getValue())) + readCallGraph(*buffer); readCallGraphsFromObjectFiles(); } Index: lld/trunk/ELF/DriverUtils.cpp =================================================================== --- lld/trunk/ELF/DriverUtils.cpp +++ lld/trunk/ELF/DriverUtils.cpp @@ -41,7 +41,7 @@ #undef PREFIX // Create table mapping all options defined in Options.td -static const opt::OptTable::Info OptInfo[] = { +static const opt::OptTable::Info optInfo[] = { #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, @@ -49,36 +49,36 @@ #undef OPTION }; -ELFOptTable::ELFOptTable() : OptTable(OptInfo) {} +ELFOptTable::ELFOptTable() : OptTable(optInfo) {} // Set color diagnostics according to -color-diagnostics={auto,always,never} // or -no-color-diagnostics flags. -static void handleColorDiagnostics(opt::InputArgList &Args) { - auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, +static void handleColorDiagnostics(opt::InputArgList &args) { + auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, OPT_no_color_diagnostics); - if (!Arg) + if (!arg) return; - if (Arg->getOption().getID() == OPT_color_diagnostics) { + if (arg->getOption().getID() == OPT_color_diagnostics) { errorHandler().ColorDiagnostics = true; - } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) { + } else if (arg->getOption().getID() == OPT_no_color_diagnostics) { errorHandler().ColorDiagnostics = false; } else { - StringRef S = Arg->getValue(); - if (S == "always") + StringRef s = arg->getValue(); + if (s == "always") errorHandler().ColorDiagnostics = true; - else if (S == "never") + else if (s == "never") errorHandler().ColorDiagnostics = false; - else if (S != "auto") - error("unknown option: --color-diagnostics=" + S); + else if (s != "auto") + error("unknown option: --color-diagnostics=" + s); } } -static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { - if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) { - StringRef S = Arg->getValue(); - if (S != "windows" && S != "posix") - error("invalid response file quoting: " + S); - if (S == "windows") +static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) { + if (auto *arg = args.getLastArg(OPT_rsp_quoting)) { + StringRef s = arg->getValue(); + if (s != "windows" && s != "posix") + error("invalid response file quoting: " + s); + if (s == "windows") return cl::TokenizeWindowsCommandLine; return cl::TokenizeGNUCommandLine; } @@ -96,56 +96,56 @@ // `--plugin-opt ` is converted to `--plugin-opt=`. This is a // bit hacky, but looks like it is still better than handling --plugin-opt // options by hand. -static void concatLTOPluginOptions(SmallVectorImpl &Args) { - SmallVector V; - for (size_t I = 0, E = Args.size(); I != E; ++I) { - StringRef S = Args[I]; - if ((S == "-plugin-opt" || S == "--plugin-opt") && I + 1 != E) { - V.push_back(Saver.save(S + "=" + Args[I + 1]).data()); - ++I; +static void concatLTOPluginOptions(SmallVectorImpl &args) { + SmallVector v; + for (size_t i = 0, e = args.size(); i != e; ++i) { + StringRef s = args[i]; + if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) { + v.push_back(Saver.save(s + "=" + args[i + 1]).data()); + ++i; } else { - V.push_back(Args[I]); + v.push_back(args[i]); } } - Args = std::move(V); + args = std::move(v); } // Parses a given list of options. -opt::InputArgList ELFOptTable::parse(ArrayRef Argv) { +opt::InputArgList ELFOptTable::parse(ArrayRef argv) { // Make InputArgList from string vectors. - unsigned MissingIndex; - unsigned MissingCount; - SmallVector Vec(Argv.data(), Argv.data() + Argv.size()); + unsigned missingIndex; + unsigned missingCount; + SmallVector vec(argv.data(), argv.data() + argv.size()); // We need to get the quoting style for response files before parsing all // options so we parse here before and ignore all the options but // --rsp-quoting. - opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); + opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); // Expand response files (arguments in the form of @) // and then parse the argument again. - cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec); - concatLTOPluginOptions(Vec); - Args = this->ParseArgs(Vec, MissingIndex, MissingCount); - - handleColorDiagnostics(Args); - if (MissingCount) - error(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); - - for (auto *Arg : Args.filtered(OPT_UNKNOWN)) { - std::string Nearest; - if (findNearest(Arg->getAsString(Args), Nearest) > 1) - error("unknown argument '" + Arg->getAsString(Args) + "'"); + cl::ExpandResponseFiles(Saver, getQuotingStyle(args), vec); + concatLTOPluginOptions(vec); + args = this->ParseArgs(vec, missingIndex, missingCount); + + handleColorDiagnostics(args); + if (missingCount) + error(Twine(args.getArgString(missingIndex)) + ": missing argument"); + + for (auto *arg : args.filtered(OPT_UNKNOWN)) { + std::string nearest; + if (findNearest(arg->getAsString(args), nearest) > 1) + error("unknown argument '" + arg->getAsString(args) + "'"); else - error("unknown argument '" + Arg->getAsString(Args) + - "', did you mean '" + Nearest + "'"); + error("unknown argument '" + arg->getAsString(args) + + "', did you mean '" + nearest + "'"); } - return Args; + return args; } void elf::printHelp() { ELFOptTable().PrintHelp( - outs(), (Config->ProgName + " [options] file...").str().c_str(), "lld", + outs(), (config->progName + " [options] file...").str().c_str(), "lld", false /*ShowHidden*/, true /*ShowAllAliases*/); outs() << "\n"; @@ -154,36 +154,36 @@ // in a message for the -help option. If it doesn't match, the scripts // assume that the linker doesn't support very basic features such as // shared libraries. Therefore, we need to print out at least "elf". - outs() << Config->ProgName << ": supported targets: elf\n"; + outs() << config->progName << ": supported targets: elf\n"; } -static std::string rewritePath(StringRef S) { - if (fs::exists(S)) - return relativeToRoot(S); - return S; +static std::string rewritePath(StringRef s) { + if (fs::exists(s)) + return relativeToRoot(s); + return s; } // Reconstructs command line arguments so that so that you can re-run // the same command with the same inputs. This is for --reproduce. -std::string elf::createResponseFile(const opt::InputArgList &Args) { - SmallString<0> Data; - raw_svector_ostream OS(Data); - OS << "--chroot .\n"; +std::string elf::createResponseFile(const opt::InputArgList &args) { + SmallString<0> data; + raw_svector_ostream os(data); + os << "--chroot .\n"; // Copy the command line to the output while rewriting paths. - for (auto *Arg : Args) { - switch (Arg->getOption().getID()) { + for (auto *arg : args) { + switch (arg->getOption().getID()) { case OPT_reproduce: break; case OPT_INPUT: - OS << quote(rewritePath(Arg->getValue())) << "\n"; + os << quote(rewritePath(arg->getValue())) << "\n"; break; case OPT_o: // If -o path contains directories, "lld @response.txt" will likely // fail because the archive we are creating doesn't contain empty // directories for the output path (-o doesn't create directories). // Strip directories to prevent the issue. - OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n"; + os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n"; break; case OPT_dynamic_list: case OPT_library_path: @@ -192,62 +192,62 @@ case OPT_symbol_ordering_file: case OPT_sysroot: case OPT_version_script: - OS << Arg->getSpelling() << " " << quote(rewritePath(Arg->getValue())) + os << arg->getSpelling() << " " << quote(rewritePath(arg->getValue())) << "\n"; break; default: - OS << toString(*Arg) << "\n"; + os << toString(*arg) << "\n"; } } - return Data.str(); + return data.str(); } // Find a file by concatenating given paths. If a resulting path // starts with "=", the character is replaced with a --sysroot value. -static Optional findFile(StringRef Path1, const Twine &Path2) { - SmallString<128> S; - if (Path1.startswith("=")) - path::append(S, Config->Sysroot, Path1.substr(1), Path2); +static Optional findFile(StringRef path1, const Twine &path2) { + SmallString<128> s; + if (path1.startswith("=")) + path::append(s, config->sysroot, path1.substr(1), path2); else - path::append(S, Path1, Path2); + path::append(s, path1, path2); - if (fs::exists(S)) - return S.str().str(); + if (fs::exists(s)) + return s.str().str(); return None; } -Optional elf::findFromSearchPaths(StringRef Path) { - for (StringRef Dir : Config->SearchPaths) - if (Optional S = findFile(Dir, Path)) - return S; +Optional elf::findFromSearchPaths(StringRef path) { + for (StringRef dir : config->searchPaths) + if (Optional s = findFile(dir, path)) + return s; return None; } // This is for -l. We'll look for lib.so or lib.a from // search paths. -Optional elf::searchLibraryBaseName(StringRef Name) { - for (StringRef Dir : Config->SearchPaths) { - if (!Config->Static) - if (Optional S = findFile(Dir, "lib" + Name + ".so")) - return S; - if (Optional S = findFile(Dir, "lib" + Name + ".a")) - return S; +Optional elf::searchLibraryBaseName(StringRef name) { + for (StringRef dir : config->searchPaths) { + if (!config->isStatic) + if (Optional s = findFile(dir, "lib" + name + ".so")) + return s; + if (Optional s = findFile(dir, "lib" + name + ".a")) + return s; } return None; } // This is for -l. -Optional elf::searchLibrary(StringRef Name) { - if (Name.startswith(":")) - return findFromSearchPaths(Name.substr(1)); - return searchLibraryBaseName (Name); +Optional elf::searchLibrary(StringRef name) { + if (name.startswith(":")) + return findFromSearchPaths(name.substr(1)); + return searchLibraryBaseName (name); } // If a linker/version script doesn't exist in the current directory, we also // look for the script in the '-L' search paths. This matches the behaviour of // '-T', --version-script=, and linker script INPUT() command in ld.bfd. -Optional elf::searchScript(StringRef Name) { - if (fs::exists(Name)) - return Name.str(); - return findFromSearchPaths(Name); +Optional elf::searchScript(StringRef name) { + if (fs::exists(name)) + return name.str(); + return findFromSearchPaths(name); } Index: lld/trunk/ELF/EhFrame.h =================================================================== --- lld/trunk/ELF/EhFrame.h +++ lld/trunk/ELF/EhFrame.h @@ -16,8 +16,8 @@ class InputSectionBase; struct EhSectionPiece; -size_t readEhRecordSize(InputSectionBase *S, size_t Off); -uint8_t getFdeEncoding(EhSectionPiece *P); +size_t readEhRecordSize(InputSectionBase *s, size_t off); +uint8_t getFdeEncoding(EhSectionPiece *p); } // namespace elf } // namespace lld Index: lld/trunk/ELF/EhFrame.cpp =================================================================== --- lld/trunk/ELF/EhFrame.cpp +++ lld/trunk/ELF/EhFrame.cpp @@ -36,72 +36,72 @@ namespace { class EhReader { public: - EhReader(InputSectionBase *S, ArrayRef D) : IS(S), D(D) {} + EhReader(InputSectionBase *s, ArrayRef d) : isec(s), d(d) {} size_t readEhRecordSize(); uint8_t getFdeEncoding(); private: - template void failOn(const P *Loc, const Twine &Msg) { - fatal("corrupted .eh_frame: " + Msg + "\n>>> defined in " + - IS->getObjMsg((const uint8_t *)Loc - IS->data().data())); + template void failOn(const P *loc, const Twine &msg) { + fatal("corrupted .eh_frame: " + msg + "\n>>> defined in " + + isec->getObjMsg((const uint8_t *)loc - isec->data().data())); } uint8_t readByte(); - void skipBytes(size_t Count); + void skipBytes(size_t count); StringRef readString(); void skipLeb128(); void skipAugP(); - InputSectionBase *IS; - ArrayRef D; + InputSectionBase *isec; + ArrayRef d; }; } -size_t elf::readEhRecordSize(InputSectionBase *S, size_t Off) { - return EhReader(S, S->data().slice(Off)).readEhRecordSize(); +size_t elf::readEhRecordSize(InputSectionBase *s, size_t off) { + return EhReader(s, s->data().slice(off)).readEhRecordSize(); } // .eh_frame section is a sequence of records. Each record starts with // a 4 byte length field. This function reads the length. size_t EhReader::readEhRecordSize() { - if (D.size() < 4) - failOn(D.data(), "CIE/FDE too small"); + if (d.size() < 4) + failOn(d.data(), "CIE/FDE too small"); // First 4 bytes of CIE/FDE is the size of the record. // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, // but we do not support that format yet. - uint64_t V = read32(D.data()); - if (V == UINT32_MAX) - failOn(D.data(), "CIE/FDE too large"); - uint64_t Size = V + 4; - if (Size > D.size()) - failOn(D.data(), "CIE/FDE ends past the end of the section"); - return Size; + uint64_t v = read32(d.data()); + if (v == UINT32_MAX) + failOn(d.data(), "CIE/FDE too large"); + uint64_t size = v + 4; + if (size > d.size()) + failOn(d.data(), "CIE/FDE ends past the end of the section"); + return size; } // Read a byte and advance D by one byte. uint8_t EhReader::readByte() { - if (D.empty()) - failOn(D.data(), "unexpected end of CIE"); - uint8_t B = D.front(); - D = D.slice(1); - return B; + if (d.empty()) + failOn(d.data(), "unexpected end of CIE"); + uint8_t b = d.front(); + d = d.slice(1); + return b; } -void EhReader::skipBytes(size_t Count) { - if (D.size() < Count) - failOn(D.data(), "CIE is too small"); - D = D.slice(Count); +void EhReader::skipBytes(size_t count) { + if (d.size() < count) + failOn(d.data(), "CIE is too small"); + d = d.slice(count); } // Read a null-terminated string. StringRef EhReader::readString() { - const uint8_t *End = llvm::find(D, '\0'); - if (End == D.end()) - failOn(D.data(), "corrupted CIE (failed to read string)"); - StringRef S = toStringRef(D.slice(0, End - D.begin())); - D = D.slice(S.size() + 1); - return S; + const uint8_t *end = llvm::find(d, '\0'); + if (end == d.end()) + failOn(d.data(), "corrupted CIE (failed to read string)"); + StringRef s = toStringRef(d.slice(0, end - d.begin())); + d = d.slice(s.size() + 1); + return s; } // Skip an integer encoded in the LEB128 format. @@ -109,21 +109,21 @@ // But we need to be at least able to skip it so that we can read // the field that follows a LEB128 number. void EhReader::skipLeb128() { - const uint8_t *ErrPos = D.data(); - while (!D.empty()) { - uint8_t Val = D.front(); - D = D.slice(1); - if ((Val & 0x80) == 0) + const uint8_t *errPos = d.data(); + while (!d.empty()) { + uint8_t val = d.front(); + d = d.slice(1); + if ((val & 0x80) == 0) return; } - failOn(ErrPos, "corrupted CIE (failed to read LEB128)"); + failOn(errPos, "corrupted CIE (failed to read LEB128)"); } -static size_t getAugPSize(unsigned Enc) { - switch (Enc & 0x0f) { +static size_t getAugPSize(unsigned enc) { + switch (enc & 0x0f) { case DW_EH_PE_absptr: case DW_EH_PE_signed: - return Config->Wordsize; + return config->wordsize; case DW_EH_PE_udata2: case DW_EH_PE_sdata2: return 2; @@ -138,29 +138,29 @@ } void EhReader::skipAugP() { - uint8_t Enc = readByte(); - if ((Enc & 0xf0) == DW_EH_PE_aligned) - failOn(D.data() - 1, "DW_EH_PE_aligned encoding is not supported"); - size_t Size = getAugPSize(Enc); - if (Size == 0) - failOn(D.data() - 1, "unknown FDE encoding"); - if (Size >= D.size()) - failOn(D.data() - 1, "corrupted CIE"); - D = D.slice(Size); + uint8_t enc = readByte(); + if ((enc & 0xf0) == DW_EH_PE_aligned) + failOn(d.data() - 1, "DW_EH_PE_aligned encoding is not supported"); + size_t size = getAugPSize(enc); + if (size == 0) + failOn(d.data() - 1, "unknown FDE encoding"); + if (size >= d.size()) + failOn(d.data() - 1, "corrupted CIE"); + d = d.slice(size); } -uint8_t elf::getFdeEncoding(EhSectionPiece *P) { - return EhReader(P->Sec, P->data()).getFdeEncoding(); +uint8_t elf::getFdeEncoding(EhSectionPiece *p) { + return EhReader(p->sec, p->data()).getFdeEncoding(); } uint8_t EhReader::getFdeEncoding() { skipBytes(8); - int Version = readByte(); - if (Version != 1 && Version != 3) - failOn(D.data() - 1, - "FDE version 1 or 3 expected, but got " + Twine(Version)); + int version = readByte(); + if (version != 1 && version != 3) + failOn(d.data() - 1, + "FDE version 1 or 3 expected, but got " + Twine(version)); - StringRef Aug = readString(); + StringRef aug = readString(); // Skip code and data alignment factors. skipLeb128(); @@ -168,7 +168,7 @@ // Skip the return address register. In CIE version 1 this is a single // byte. In CIE version 3 this is an unsigned LEB128. - if (Version == 1) + if (version == 1) readByte(); else skipLeb128(); @@ -176,22 +176,22 @@ // We only care about an 'R' value, but other records may precede an 'R' // record. Unfortunately records are not in TLV (type-length-value) format, // so we need to teach the linker how to skip records for each type. - for (char C : Aug) { - if (C == 'R') + for (char c : aug) { + if (c == 'R') return readByte(); - if (C == 'z') { + if (c == 'z') { skipLeb128(); continue; } - if (C == 'P') { + if (c == 'P') { skipAugP(); continue; } - if (C == 'L') { + if (c == 'L') { readByte(); continue; } - failOn(Aug.data(), "unknown .eh_frame augmentation string: " + Aug); + failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug); } return DW_EH_PE_absptr; } Index: lld/trunk/ELF/ICF.cpp =================================================================== --- lld/trunk/ELF/ICF.cpp +++ lld/trunk/ELF/ICF.cpp @@ -98,33 +98,33 @@ void run(); private: - void segregate(size_t Begin, size_t End, bool Constant); + void segregate(size_t begin, size_t end, bool constant); template - bool constantEq(const InputSection *A, ArrayRef RelsA, - const InputSection *B, ArrayRef RelsB); + bool constantEq(const InputSection *a, ArrayRef relsA, + const InputSection *b, ArrayRef relsB); template - bool variableEq(const InputSection *A, ArrayRef RelsA, - const InputSection *B, ArrayRef RelsB); + bool variableEq(const InputSection *a, ArrayRef relsA, + const InputSection *b, ArrayRef relsB); - bool equalsConstant(const InputSection *A, const InputSection *B); - bool equalsVariable(const InputSection *A, const InputSection *B); + bool equalsConstant(const InputSection *a, const InputSection *b); + bool equalsVariable(const InputSection *a, const InputSection *b); - size_t findBoundary(size_t Begin, size_t End); + size_t findBoundary(size_t begin, size_t end); - void forEachClassRange(size_t Begin, size_t End, - llvm::function_ref Fn); + void forEachClassRange(size_t begin, size_t end, + llvm::function_ref fn); - void forEachClass(llvm::function_ref Fn); + void forEachClass(llvm::function_ref fn); - std::vector Sections; + std::vector sections; // We repeat the main loop while `Repeat` is true. - std::atomic Repeat; + std::atomic repeat; // The main loop counter. - int Cnt = 0; + int cnt = 0; // We have two locations for equivalence classes. On the first iteration // of the main loop, Class[0] has a valid value, and Class[1] contains @@ -150,42 +150,42 @@ // because we can safely read the next class without worrying about race // conditions. Using the same location makes this algorithm converge // faster because it uses results of the same iteration earlier. - int Current = 0; - int Next = 0; + int current = 0; + int next = 0; }; } // Returns true if section S is subject of ICF. -static bool isEligible(InputSection *S) { - if (!S->isLive() || S->KeepUnique || !(S->Flags & SHF_ALLOC)) +static bool isEligible(InputSection *s) { + if (!s->isLive() || s->keepUnique || !(s->flags & SHF_ALLOC)) return false; // Don't merge writable sections. .data.rel.ro sections are marked as writable // but are semantically read-only. - if ((S->Flags & SHF_WRITE) && S->Name != ".data.rel.ro" && - !S->Name.startswith(".data.rel.ro.")) + if ((s->flags & SHF_WRITE) && s->name != ".data.rel.ro" && + !s->name.startswith(".data.rel.ro.")) return false; // SHF_LINK_ORDER sections are ICF'd as a unit with their dependent sections, // so we don't consider them for ICF individually. - if (S->Flags & SHF_LINK_ORDER) + if (s->flags & SHF_LINK_ORDER) return false; // Don't merge synthetic sections as their Data member is not valid and empty. // The Data member needs to be valid for ICF as it is used by ICF to determine // the equality of section contents. - if (isa(S)) + if (isa(s)) return false; // .init and .fini contains instructions that must be executed to initialize // and finalize the process. They cannot and should not be merged. - if (S->Name == ".init" || S->Name == ".fini") + if (s->name == ".init" || s->name == ".fini") return false; // A user program may enumerate sections named with a C identifier using // __start_* and __stop_* symbols. We cannot ICF any such sections because // that could change program semantics. - if (isValidCIdentifier(S->Name)) + if (isValidCIdentifier(s->name)) return false; return true; @@ -193,7 +193,7 @@ // Split an equivalence class into smaller classes. template -void ICF::segregate(size_t Begin, size_t End, bool Constant) { +void ICF::segregate(size_t begin, size_t end, bool constant) { // This loop rearranges sections in [Begin, End) so that all sections // that are equal in terms of equals{Constant,Variable} are contiguous // in [Begin, End). @@ -202,93 +202,93 @@ // issue in practice because the number of the distinct sections in // each range is usually very small. - while (Begin < End) { + while (begin < end) { // Divide [Begin, End) into two. Let Mid be the start index of the // second group. - auto Bound = - std::stable_partition(Sections.begin() + Begin + 1, - Sections.begin() + End, [&](InputSection *S) { - if (Constant) - return equalsConstant(Sections[Begin], S); - return equalsVariable(Sections[Begin], S); + auto bound = + std::stable_partition(sections.begin() + begin + 1, + sections.begin() + end, [&](InputSection *s) { + if (constant) + return equalsConstant(sections[begin], s); + return equalsVariable(sections[begin], s); }); - size_t Mid = Bound - Sections.begin(); + size_t mid = bound - sections.begin(); // Now we split [Begin, End) into [Begin, Mid) and [Mid, End) by // updating the sections in [Begin, Mid). We use Mid as an equivalence // class ID because every group ends with a unique index. - for (size_t I = Begin; I < Mid; ++I) - Sections[I]->Class[Next] = Mid; + for (size_t i = begin; i < mid; ++i) + sections[i]->eqClass[next] = mid; // If we created a group, we need to iterate the main loop again. - if (Mid != End) - Repeat = true; + if (mid != end) + repeat = true; - Begin = Mid; + begin = mid; } } // Compare two lists of relocations. template template -bool ICF::constantEq(const InputSection *SecA, ArrayRef RA, - const InputSection *SecB, ArrayRef RB) { - for (size_t I = 0; I < RA.size(); ++I) { - if (RA[I].r_offset != RB[I].r_offset || - RA[I].getType(Config->IsMips64EL) != RB[I].getType(Config->IsMips64EL)) +bool ICF::constantEq(const InputSection *secA, ArrayRef ra, + const InputSection *secB, ArrayRef rb) { + for (size_t i = 0; i < ra.size(); ++i) { + if (ra[i].r_offset != rb[i].r_offset || + ra[i].getType(config->isMips64EL) != rb[i].getType(config->isMips64EL)) return false; - uint64_t AddA = getAddend(RA[I]); - uint64_t AddB = getAddend(RB[I]); - - Symbol &SA = SecA->template getFile()->getRelocTargetSym(RA[I]); - Symbol &SB = SecB->template getFile()->getRelocTargetSym(RB[I]); - if (&SA == &SB) { - if (AddA == AddB) + uint64_t addA = getAddend(ra[i]); + uint64_t addB = getAddend(rb[i]); + + Symbol &sa = secA->template getFile()->getRelocTargetSym(ra[i]); + Symbol &sb = secB->template getFile()->getRelocTargetSym(rb[i]); + if (&sa == &sb) { + if (addA == addB) continue; return false; } - auto *DA = dyn_cast(&SA); - auto *DB = dyn_cast(&SB); + auto *da = dyn_cast(&sa); + auto *db = dyn_cast(&sb); // Placeholder symbols generated by linker scripts look the same now but // may have different values later. - if (!DA || !DB || DA->ScriptDefined || DB->ScriptDefined) + if (!da || !db || da->scriptDefined || db->scriptDefined) return false; // Relocations referring to absolute symbols are constant-equal if their // values are equal. - if (!DA->Section && !DB->Section && DA->Value + AddA == DB->Value + AddB) + if (!da->section && !db->section && da->value + addA == db->value + addB) continue; - if (!DA->Section || !DB->Section) + if (!da->section || !db->section) return false; - if (DA->Section->kind() != DB->Section->kind()) + if (da->section->kind() != db->section->kind()) return false; // Relocations referring to InputSections are constant-equal if their // section offsets are equal. - if (isa(DA->Section)) { - if (DA->Value + AddA == DB->Value + AddB) + if (isa(da->section)) { + if (da->value + addA == db->value + addB) continue; return false; } // Relocations referring to MergeInputSections are constant-equal if their // offsets in the output section are equal. - auto *X = dyn_cast(DA->Section); - if (!X) + auto *x = dyn_cast(da->section); + if (!x) return false; - auto *Y = cast(DB->Section); - if (X->getParent() != Y->getParent()) + auto *y = cast(db->section); + if (x->getParent() != y->getParent()) return false; - uint64_t OffsetA = - SA.isSection() ? X->getOffset(AddA) : X->getOffset(DA->Value) + AddA; - uint64_t OffsetB = - SB.isSection() ? Y->getOffset(AddB) : Y->getOffset(DB->Value) + AddB; - if (OffsetA != OffsetB) + uint64_t offsetA = + sa.isSection() ? x->getOffset(addA) : x->getOffset(da->value) + addA; + uint64_t offsetB = + sb.isSection() ? y->getOffset(addB) : y->getOffset(db->value) + addB; + if (offsetA != offsetB) return false; } @@ -298,57 +298,57 @@ // Compare "non-moving" part of two InputSections, namely everything // except relocation targets. template -bool ICF::equalsConstant(const InputSection *A, const InputSection *B) { - if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags || - A->getSize() != B->getSize() || A->data() != B->data()) +bool ICF::equalsConstant(const InputSection *a, const InputSection *b) { + if (a->numRelocations != b->numRelocations || a->flags != b->flags || + a->getSize() != b->getSize() || a->data() != b->data()) return false; // If two sections have different output sections, we cannot merge them. // FIXME: This doesn't do the right thing in the case where there is a linker // script. We probably need to move output section assignment before ICF to // get the correct behaviour here. - if (getOutputSectionName(A) != getOutputSectionName(B)) + if (getOutputSectionName(a) != getOutputSectionName(b)) return false; - if (A->AreRelocsRela) - return constantEq(A, A->template relas(), B, - B->template relas()); - return constantEq(A, A->template rels(), B, B->template rels()); + if (a->areRelocsRela) + return constantEq(a, a->template relas(), b, + b->template relas()); + return constantEq(a, a->template rels(), b, b->template rels()); } // Compare two lists of relocations. Returns true if all pairs of // relocations point to the same section in terms of ICF. template template -bool ICF::variableEq(const InputSection *SecA, ArrayRef RA, - const InputSection *SecB, ArrayRef RB) { - assert(RA.size() == RB.size()); +bool ICF::variableEq(const InputSection *secA, ArrayRef ra, + const InputSection *secB, ArrayRef rb) { + assert(ra.size() == rb.size()); - for (size_t I = 0; I < RA.size(); ++I) { + for (size_t i = 0; i < ra.size(); ++i) { // The two sections must be identical. - Symbol &SA = SecA->template getFile()->getRelocTargetSym(RA[I]); - Symbol &SB = SecB->template getFile()->getRelocTargetSym(RB[I]); - if (&SA == &SB) + Symbol &sa = secA->template getFile()->getRelocTargetSym(ra[i]); + Symbol &sb = secB->template getFile()->getRelocTargetSym(rb[i]); + if (&sa == &sb) continue; - auto *DA = cast(&SA); - auto *DB = cast(&SB); + auto *da = cast(&sa); + auto *db = cast(&sb); // We already dealt with absolute and non-InputSection symbols in // constantEq, and for InputSections we have already checked everything // except the equivalence class. - if (!DA->Section) + if (!da->section) continue; - auto *X = dyn_cast(DA->Section); - if (!X) + auto *x = dyn_cast(da->section); + if (!x) continue; - auto *Y = cast(DB->Section); + auto *y = cast(db->section); // Ineligible sections are in the special equivalence class 0. // They can never be the same in terms of the equivalence class. - if (X->Class[Current] == 0) + if (x->eqClass[current] == 0) return false; - if (X->Class[Current] != Y->Class[Current]) + if (x->eqClass[current] != y->eqClass[current]) return false; }; @@ -357,19 +357,19 @@ // Compare "moving" part of two InputSections, namely relocation targets. template -bool ICF::equalsVariable(const InputSection *A, const InputSection *B) { - if (A->AreRelocsRela) - return variableEq(A, A->template relas(), B, - B->template relas()); - return variableEq(A, A->template rels(), B, B->template rels()); +bool ICF::equalsVariable(const InputSection *a, const InputSection *b) { + if (a->areRelocsRela) + return variableEq(a, a->template relas(), b, + b->template relas()); + return variableEq(a, a->template rels(), b, b->template rels()); } -template size_t ICF::findBoundary(size_t Begin, size_t End) { - uint32_t Class = Sections[Begin]->Class[Current]; - for (size_t I = Begin + 1; I < End; ++I) - if (Class != Sections[I]->Class[Current]) - return I; - return End; +template size_t ICF::findBoundary(size_t begin, size_t end) { + uint32_t eqClass = sections[begin]->eqClass[current]; + for (size_t i = begin + 1; i < end; ++i) + if (eqClass != sections[i]->eqClass[current]) + return i; + return end; } // Sections in the same equivalence class are contiguous in Sections @@ -378,125 +378,125 @@ // // This function calls Fn on every group within [Begin, End). template -void ICF::forEachClassRange(size_t Begin, size_t End, - llvm::function_ref Fn) { - while (Begin < End) { - size_t Mid = findBoundary(Begin, End); - Fn(Begin, Mid); - Begin = Mid; +void ICF::forEachClassRange(size_t begin, size_t end, + llvm::function_ref fn) { + while (begin < end) { + size_t mid = findBoundary(begin, end); + fn(begin, mid); + begin = mid; } } // Call Fn on each equivalence class. template -void ICF::forEachClass(llvm::function_ref Fn) { +void ICF::forEachClass(llvm::function_ref fn) { // If threading is disabled or the number of sections are // too small to use threading, call Fn sequentially. - if (!ThreadsEnabled || Sections.size() < 1024) { - forEachClassRange(0, Sections.size(), Fn); - ++Cnt; + if (!ThreadsEnabled || sections.size() < 1024) { + forEachClassRange(0, sections.size(), fn); + ++cnt; return; } - Current = Cnt % 2; - Next = (Cnt + 1) % 2; + current = cnt % 2; + next = (cnt + 1) % 2; // Shard into non-overlapping intervals, and call Fn in parallel. // The sharding must be completed before any calls to Fn are made // so that Fn can modify the Chunks in its shard without causing data // races. - const size_t NumShards = 256; - size_t Step = Sections.size() / NumShards; - size_t Boundaries[NumShards + 1]; - Boundaries[0] = 0; - Boundaries[NumShards] = Sections.size(); + const size_t numShards = 256; + size_t step = sections.size() / numShards; + size_t boundaries[numShards + 1]; + boundaries[0] = 0; + boundaries[numShards] = sections.size(); - parallelForEachN(1, NumShards, [&](size_t I) { - Boundaries[I] = findBoundary((I - 1) * Step, Sections.size()); + parallelForEachN(1, numShards, [&](size_t i) { + boundaries[i] = findBoundary((i - 1) * step, sections.size()); }); - parallelForEachN(1, NumShards + 1, [&](size_t I) { - if (Boundaries[I - 1] < Boundaries[I]) - forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn); + parallelForEachN(1, numShards + 1, [&](size_t i) { + if (boundaries[i - 1] < boundaries[i]) + forEachClassRange(boundaries[i - 1], boundaries[i], fn); }); - ++Cnt; + ++cnt; } // Combine the hashes of the sections referenced by the given section into its // hash. template -static void combineRelocHashes(unsigned Cnt, InputSection *IS, - ArrayRef Rels) { - uint32_t Hash = IS->Class[Cnt % 2]; - for (RelTy Rel : Rels) { - Symbol &S = IS->template getFile()->getRelocTargetSym(Rel); - if (auto *D = dyn_cast(&S)) - if (auto *RelSec = dyn_cast_or_null(D->Section)) - Hash += RelSec->Class[Cnt % 2]; +static void combineRelocHashes(unsigned cnt, InputSection *isec, + ArrayRef rels) { + uint32_t hash = isec->eqClass[cnt % 2]; + for (RelTy rel : rels) { + Symbol &s = isec->template getFile()->getRelocTargetSym(rel); + if (auto *d = dyn_cast(&s)) + if (auto *relSec = dyn_cast_or_null(d->section)) + hash += relSec->eqClass[cnt % 2]; } // Set MSB to 1 to avoid collisions with non-hash IDs. - IS->Class[(Cnt + 1) % 2] = Hash | (1U << 31); + isec->eqClass[(cnt + 1) % 2] = hash | (1U << 31); } -static void print(const Twine &S) { - if (Config->PrintIcfSections) - message(S); +static void print(const Twine &s) { + if (config->printIcfSections) + message(s); } // The main function of ICF. template void ICF::run() { // Collect sections to merge. - for (InputSectionBase *Sec : InputSections) - if (auto *S = dyn_cast(Sec)) - if (isEligible(S)) - Sections.push_back(S); + for (InputSectionBase *sec : inputSections) + if (auto *s = dyn_cast(sec)) + if (isEligible(s)) + sections.push_back(s); // Initially, we use hash values to partition sections. - parallelForEach(Sections, [&](InputSection *S) { - S->Class[0] = xxHash64(S->data()); + parallelForEach(sections, [&](InputSection *s) { + s->eqClass[0] = xxHash64(s->data()); }); - for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { - parallelForEach(Sections, [&](InputSection *S) { - if (S->AreRelocsRela) - combineRelocHashes(Cnt, S, S->template relas()); + for (unsigned cnt = 0; cnt != 2; ++cnt) { + parallelForEach(sections, [&](InputSection *s) { + if (s->areRelocsRela) + combineRelocHashes(cnt, s, s->template relas()); else - combineRelocHashes(Cnt, S, S->template rels()); + combineRelocHashes(cnt, s, s->template rels()); }); } // From now on, sections in Sections vector are ordered so that sections // in the same equivalence class are consecutive in the vector. - llvm::stable_sort(Sections, [](const InputSection *A, const InputSection *B) { - return A->Class[0] < B->Class[0]; + llvm::stable_sort(sections, [](const InputSection *a, const InputSection *b) { + return a->eqClass[0] < b->eqClass[0]; }); // Compare static contents and assign unique IDs for each static content. - forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); }); + forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); }); // Split groups by comparing relocations until convergence is obtained. do { - Repeat = false; + repeat = false; forEachClass( - [&](size_t Begin, size_t End) { segregate(Begin, End, false); }); - } while (Repeat); + [&](size_t begin, size_t end) { segregate(begin, end, false); }); + } while (repeat); - log("ICF needed " + Twine(Cnt) + " iterations"); + log("ICF needed " + Twine(cnt) + " iterations"); // Merge sections by the equivalence class. - forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) { - if (End - Begin == 1) + forEachClassRange(0, sections.size(), [&](size_t begin, size_t end) { + if (end - begin == 1) return; - print("selected section " + toString(Sections[Begin])); - for (size_t I = Begin + 1; I < End; ++I) { - print(" removing identical section " + toString(Sections[I])); - Sections[Begin]->replace(Sections[I]); + print("selected section " + toString(sections[begin])); + for (size_t i = begin + 1; i < end; ++i) { + print(" removing identical section " + toString(sections[i])); + sections[begin]->replace(sections[i]); // At this point we know sections merged are fully identical and hence // we want to remove duplicate implicit dependencies such as link order // and relocation sections. - for (InputSection *IS : Sections[I]->DependentSections) - IS->markDead(); + for (InputSection *isec : sections[i]->dependentSections) + isec->markDead(); } }); } Index: lld/trunk/ELF/InputFiles.h =================================================================== --- lld/trunk/ELF/InputFiles.h +++ lld/trunk/ELF/InputFiles.h @@ -39,7 +39,7 @@ } // Returns "", "foo.a(bar.o)" or "baz.o". -std::string toString(const elf::InputFile *F); +std::string toString(const elf::InputFile *f); namespace elf { @@ -49,13 +49,13 @@ // If -reproduce option is given, all input files are written // to this tar archive. -extern std::unique_ptr Tar; +extern std::unique_ptr tar; // Opens a given file. -llvm::Optional readFile(StringRef Path); +llvm::Optional readFile(StringRef path); // Add symbols in File to the symbol table. -void parseFile(InputFile *File); +void parseFile(InputFile *file); // The root class of input files. class InputFile { @@ -69,21 +69,21 @@ BinaryKind, }; - Kind kind() const { return FileKind; } + Kind kind() const { return fileKind; } bool isElf() const { - Kind K = kind(); - return K == ObjKind || K == SharedKind; + Kind k = kind(); + return k == ObjKind || k == SharedKind; } - StringRef getName() const { return MB.getBufferIdentifier(); } - MemoryBufferRef MB; + StringRef getName() const { return mb.getBufferIdentifier(); } + MemoryBufferRef mb; // Returns sections. It is a runtime error to call this function // on files that don't have the notion of sections. ArrayRef getSections() const { - assert(FileKind == ObjKind || FileKind == BinaryKind); - return Sections; + assert(fileKind == ObjKind || fileKind == BinaryKind); + return sections; } // Returns object file symbols. It is a runtime error to call this @@ -91,35 +91,35 @@ ArrayRef getSymbols() { return getMutableSymbols(); } MutableArrayRef getMutableSymbols() { - assert(FileKind == BinaryKind || FileKind == ObjKind || - FileKind == BitcodeKind); - return Symbols; + assert(fileKind == BinaryKind || fileKind == ObjKind || + fileKind == BitcodeKind); + return symbols; } // Filename of .a which contained this file. If this file was // not in an archive file, it is the empty string. We use this // string for creating error messages. - std::string ArchiveName; + std::string archiveName; // If this is an architecture-specific file, the following members // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type. - ELFKind EKind = ELFNoneKind; - uint16_t EMachine = llvm::ELF::EM_NONE; - uint8_t OSABI = 0; - uint8_t ABIVersion = 0; + ELFKind ekind = ELFNoneKind; + uint16_t emachine = llvm::ELF::EM_NONE; + uint8_t osabi = 0; + uint8_t abiVersion = 0; // Cache for toString(). Only toString() should use this member. - mutable std::string ToStringCache; + mutable std::string toStringCache; - std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, - uint64_t Offset); + std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec, + uint64_t offset); // True if this is an argument for --just-symbols. Usually false. - bool JustSymbols = false; + bool justSymbols = false; // OutSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE // to compute offsets in PLT call stubs. - uint32_t PPC32Got2OutSecOff = 0; + uint32_t ppc32Got2OutSecOff = 0; // On PPC64 we need to keep track of which files contain small code model // relocations that access the .toc section. To minimize the chance of a @@ -130,56 +130,56 @@ // code model relocations support immediates in the range [-0x8000, 0x7FFC], // making the addressable range relative to the toc pointer // [.got, .got + 0xFFFC]. - bool PPC64SmallCodeModelTocRelocs = false; + bool ppc64SmallCodeModelTocRelocs = false; // GroupId is used for --warn-backrefs which is an optional error // checking feature. All files within the same --{start,end}-group or // --{start,end}-lib get the same group ID. Otherwise, each file gets a new // group ID. For more info, see checkDependency() in SymbolTable.cpp. - uint32_t GroupId; - static bool IsInGroup; - static uint32_t NextGroupId; + uint32_t groupId; + static bool isInGroup; + static uint32_t nextGroupId; // Index of MIPS GOT built for this file. - llvm::Optional MipsGotIndex; + llvm::Optional mipsGotIndex; - std::vector Symbols; + std::vector symbols; protected: - InputFile(Kind K, MemoryBufferRef M); - std::vector Sections; + InputFile(Kind k, MemoryBufferRef m); + std::vector sections; private: - const Kind FileKind; + const Kind fileKind; }; class ELFFileBase : public InputFile { public: - ELFFileBase(Kind K, MemoryBufferRef M); - static bool classof(const InputFile *F) { return F->isElf(); } + ELFFileBase(Kind k, MemoryBufferRef m); + static bool classof(const InputFile *f) { return f->isElf(); } template llvm::object::ELFFile getObj() const { - return check(llvm::object::ELFFile::create(MB.getBuffer())); + return check(llvm::object::ELFFile::create(mb.getBuffer())); } - StringRef getStringTable() const { return StringTable; } + StringRef getStringTable() const { return stringTable; } template typename ELFT::SymRange getELFSyms() const { return typename ELFT::SymRange( - reinterpret_cast(ELFSyms), NumELFSyms); + reinterpret_cast(elfSyms), numELFSyms); } template typename ELFT::SymRange getGlobalELFSyms() const { - return getELFSyms().slice(FirstGlobal); + return getELFSyms().slice(firstGlobal); } protected: // Initializes this class's member variables. template void init(); - const void *ELFSyms = nullptr; - size_t NumELFSyms = 0; - uint32_t FirstGlobal = 0; - StringRef StringTable; + const void *elfSyms = nullptr; + size_t numELFSyms = 0; + uint32_t firstGlobal = 0; + StringRef stringTable; }; // .o file. @@ -192,7 +192,7 @@ using Elf_CGProfile = typename ELFT::CGProfile; public: - static bool classof(const InputFile *F) { return F->kind() == ObjKind; } + static bool classof(const InputFile *f) { return f->kind() == ObjKind; } llvm::object::ELFFile getObj() const { return this->ELFFileBase::getObj(); @@ -201,67 +201,67 @@ ArrayRef getLocalSymbols(); ArrayRef getGlobalSymbols(); - ObjFile(MemoryBufferRef M, StringRef ArchiveName) : ELFFileBase(ObjKind, M) { - this->ArchiveName = ArchiveName; + ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { + this->archiveName = archiveName; } - void parse(bool IgnoreComdats = false); + void parse(bool ignoreComdats = false); - StringRef getShtGroupSignature(ArrayRef Sections, - const Elf_Shdr &Sec); + StringRef getShtGroupSignature(ArrayRef sections, + const Elf_Shdr &sec); - Symbol &getSymbol(uint32_t SymbolIndex) const { - if (SymbolIndex >= this->Symbols.size()) + Symbol &getSymbol(uint32_t symbolIndex) const { + if (symbolIndex >= this->symbols.size()) fatal(toString(this) + ": invalid symbol index"); - return *this->Symbols[SymbolIndex]; + return *this->symbols[symbolIndex]; } - uint32_t getSectionIndex(const Elf_Sym &Sym) const; + uint32_t getSectionIndex(const Elf_Sym &sym) const; - template Symbol &getRelocTargetSym(const RelT &Rel) const { - uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); - return getSymbol(SymIndex); + template Symbol &getRelocTargetSym(const RelT &rel) const { + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + return getSymbol(symIndex); } llvm::Optional getDILineInfo(InputSectionBase *, uint64_t); - llvm::Optional> getVariableLoc(StringRef Name); + llvm::Optional> getVariableLoc(StringRef name); // MIPS GP0 value defined by this file. This value represents the gp value // used to create the relocatable object and required to support // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations. - uint32_t MipsGp0 = 0; + uint32_t mipsGp0 = 0; - uint32_t AndFeatures = 0; + uint32_t andFeatures = 0; // Name of source file obtained from STT_FILE symbol value, // or empty string if there is no such symbol in object file // symbol table. - StringRef SourceFile; + StringRef sourceFile; // True if the file defines functions compiled with // -fsplit-stack. Usually false. - bool SplitStack = false; + bool splitStack = false; // True if the file defines functions compiled with -fsplit-stack, // but had one or more functions with the no_split_stack attribute. - bool SomeNoSplitStack = false; + bool someNoSplitStack = false; // Pointer to this input file's .llvm_addrsig section, if it has one. - const Elf_Shdr *AddrsigSec = nullptr; + const Elf_Shdr *addrsigSec = nullptr; // SHT_LLVM_CALL_GRAPH_PROFILE table - ArrayRef CGProfile; + ArrayRef cgProfile; private: - void initializeSections(bool IgnoreComdats); + void initializeSections(bool ignoreComdats); void initializeSymbols(); void initializeJustSymbols(); void initializeDwarf(); - InputSectionBase *getRelocTarget(const Elf_Shdr &Sec); - InputSectionBase *createInputSection(const Elf_Shdr &Sec); - StringRef getSectionName(const Elf_Shdr &Sec); + InputSectionBase *getRelocTarget(const Elf_Shdr &sec); + InputSectionBase *createInputSection(const Elf_Shdr &sec); + StringRef getSectionName(const Elf_Shdr &sec); - bool shouldMerge(const Elf_Shdr &Sec); + bool shouldMerge(const Elf_Shdr &sec); // Each ELF symbol contains a section index which the symbol belongs to. // However, because the number of bits dedicated for that is limited, a @@ -275,24 +275,24 @@ // // The following variable contains the contents of .symtab_shndx. // If the section does not exist (which is common), the array is empty. - ArrayRef ShndxTable; + ArrayRef shndxTable; // .shstrtab contents. - StringRef SectionStringTable; + StringRef sectionStringTable; // Debugging information to retrieve source file and line for error // reporting. Linker may find reasonable number of errors in a // single object file, so we cache debugging information in order to // parse it only once for each object file we link. - std::unique_ptr Dwarf; - std::vector LineTables; + std::unique_ptr dwarf; + std::vector lineTables; struct VarLoc { - const llvm::DWARFDebugLine::LineTable *LT; - unsigned File; - unsigned Line; + const llvm::DWARFDebugLine::LineTable *lt; + unsigned file; + unsigned line; }; - llvm::DenseMap VariableLoc; - llvm::once_flag InitDwarfLine; + llvm::DenseMap variableLoc; + llvm::once_flag initDwarfLine; }; // LazyObjFile is analogous to ArchiveFile in the sense that @@ -304,100 +304,100 @@ // archive file semantics. class LazyObjFile : public InputFile { public: - LazyObjFile(MemoryBufferRef M, StringRef ArchiveName, - uint64_t OffsetInArchive) - : InputFile(LazyObjKind, M), OffsetInArchive(OffsetInArchive) { - this->ArchiveName = ArchiveName; + LazyObjFile(MemoryBufferRef m, StringRef archiveName, + uint64_t offsetInArchive) + : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) { + this->archiveName = archiveName; } - static bool classof(const InputFile *F) { return F->kind() == LazyObjKind; } + static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; } template void parse(); void fetch(); private: - uint64_t OffsetInArchive; + uint64_t offsetInArchive; }; // An ArchiveFile object represents a .a file. class ArchiveFile : public InputFile { public: - explicit ArchiveFile(std::unique_ptr &&File); - static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } + explicit ArchiveFile(std::unique_ptr &&file); + static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } void parse(); // Pulls out an object file that contains a definition for Sym and // returns it. If the same file was instantiated before, this // function does nothing (so we don't instantiate the same file // more than once.) - void fetch(const Archive::Symbol &Sym); + void fetch(const Archive::Symbol &sym); private: - std::unique_ptr File; - llvm::DenseSet Seen; + std::unique_ptr file; + llvm::DenseSet seen; }; class BitcodeFile : public InputFile { public: - BitcodeFile(MemoryBufferRef M, StringRef ArchiveName, - uint64_t OffsetInArchive); - static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; } + BitcodeFile(MemoryBufferRef m, StringRef archiveName, + uint64_t offsetInArchive); + static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } template void parse(); - std::unique_ptr Obj; + std::unique_ptr obj; }; // .so file. class SharedFile : public ELFFileBase { public: - SharedFile(MemoryBufferRef M, StringRef DefaultSoName) - : ELFFileBase(SharedKind, M), SoName(DefaultSoName), - IsNeeded(!Config->AsNeeded) {} + SharedFile(MemoryBufferRef m, StringRef defaultSoName) + : ELFFileBase(SharedKind, m), soName(defaultSoName), + isNeeded(!config->asNeeded) {} // This is actually a vector of Elf_Verdef pointers. - std::vector Verdefs; + std::vector verdefs; // If the output file needs Elf_Verneed data structures for this file, this is // a vector of Elf_Vernaux version identifiers that map onto the entries in // Verdefs, otherwise it is empty. - std::vector Vernauxs; + std::vector vernauxs; - static unsigned VernauxNum; + static unsigned vernauxNum; - std::vector DtNeeded; - std::string SoName; + std::vector dtNeeded; + std::string soName; - static bool classof(const InputFile *F) { return F->kind() == SharedKind; } + static bool classof(const InputFile *f) { return f->kind() == SharedKind; } template void parse(); // Used for --no-allow-shlib-undefined. - bool AllNeededIsKnown; + bool allNeededIsKnown; // Used for --as-needed - bool IsNeeded; + bool isNeeded; }; class BinaryFile : public InputFile { public: - explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} - static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } + explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {} + static bool classof(const InputFile *f) { return f->kind() == BinaryKind; } void parse(); }; -InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", - uint64_t OffsetInArchive = 0); +InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "", + uint64_t offsetInArchive = 0); -inline bool isBitcode(MemoryBufferRef MB) { - return identify_magic(MB.getBuffer()) == llvm::file_magic::bitcode; +inline bool isBitcode(MemoryBufferRef mb) { + return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode; } -std::string replaceThinLTOSuffix(StringRef Path); +std::string replaceThinLTOSuffix(StringRef path); -extern std::vector BinaryFiles; -extern std::vector BitcodeFiles; -extern std::vector LazyObjFiles; -extern std::vector ObjectFiles; -extern std::vector SharedFiles; +extern std::vector binaryFiles; +extern std::vector bitcodeFiles; +extern std::vector lazyObjFiles; +extern std::vector objectFiles; +extern std::vector sharedFiles; } // namespace elf } // namespace lld Index: lld/trunk/ELF/InputFiles.cpp =================================================================== --- lld/trunk/ELF/InputFiles.cpp +++ lld/trunk/ELF/InputFiles.cpp @@ -40,167 +40,167 @@ using namespace lld; using namespace lld::elf; -bool InputFile::IsInGroup; -uint32_t InputFile::NextGroupId; -std::vector elf::BinaryFiles; -std::vector elf::BitcodeFiles; -std::vector elf::LazyObjFiles; -std::vector elf::ObjectFiles; -std::vector elf::SharedFiles; - -std::unique_ptr elf::Tar; - -static ELFKind getELFKind(MemoryBufferRef MB, StringRef ArchiveName) { - unsigned char Size; - unsigned char Endian; - std::tie(Size, Endian) = getElfArchType(MB.getBuffer()); - - auto Report = [&](StringRef Msg) { - StringRef Filename = MB.getBufferIdentifier(); - if (ArchiveName.empty()) - fatal(Filename + ": " + Msg); +bool InputFile::isInGroup; +uint32_t InputFile::nextGroupId; +std::vector elf::binaryFiles; +std::vector elf::bitcodeFiles; +std::vector elf::lazyObjFiles; +std::vector elf::objectFiles; +std::vector elf::sharedFiles; + +std::unique_ptr elf::tar; + +static ELFKind getELFKind(MemoryBufferRef mb, StringRef archiveName) { + unsigned char size; + unsigned char endian; + std::tie(size, endian) = getElfArchType(mb.getBuffer()); + + auto report = [&](StringRef msg) { + StringRef filename = mb.getBufferIdentifier(); + if (archiveName.empty()) + fatal(filename + ": " + msg); else - fatal(ArchiveName + "(" + Filename + "): " + Msg); + fatal(archiveName + "(" + filename + "): " + msg); }; - if (!MB.getBuffer().startswith(ElfMagic)) - Report("not an ELF file"); - if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB) - Report("corrupted ELF file: invalid data encoding"); - if (Size != ELFCLASS32 && Size != ELFCLASS64) - Report("corrupted ELF file: invalid file class"); - - size_t BufSize = MB.getBuffer().size(); - if ((Size == ELFCLASS32 && BufSize < sizeof(Elf32_Ehdr)) || - (Size == ELFCLASS64 && BufSize < sizeof(Elf64_Ehdr))) - Report("corrupted ELF file: file is too short"); - - if (Size == ELFCLASS32) - return (Endian == ELFDATA2LSB) ? ELF32LEKind : ELF32BEKind; - return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; + if (!mb.getBuffer().startswith(ElfMagic)) + report("not an ELF file"); + if (endian != ELFDATA2LSB && endian != ELFDATA2MSB) + report("corrupted ELF file: invalid data encoding"); + if (size != ELFCLASS32 && size != ELFCLASS64) + report("corrupted ELF file: invalid file class"); + + size_t bufSize = mb.getBuffer().size(); + if ((size == ELFCLASS32 && bufSize < sizeof(Elf32_Ehdr)) || + (size == ELFCLASS64 && bufSize < sizeof(Elf64_Ehdr))) + report("corrupted ELF file: file is too short"); + + if (size == ELFCLASS32) + return (endian == ELFDATA2LSB) ? ELF32LEKind : ELF32BEKind; + return (endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; } -InputFile::InputFile(Kind K, MemoryBufferRef M) - : MB(M), GroupId(NextGroupId), FileKind(K) { +InputFile::InputFile(Kind k, MemoryBufferRef m) + : mb(m), groupId(nextGroupId), fileKind(k) { // All files within the same --{start,end}-group get the same group ID. // Otherwise, a new file will get a new group ID. - if (!IsInGroup) - ++NextGroupId; + if (!isInGroup) + ++nextGroupId; } -Optional elf::readFile(StringRef Path) { +Optional elf::readFile(StringRef path) { // The --chroot option changes our virtual root directory. // This is useful when you are dealing with files created by --reproduce. - if (!Config->Chroot.empty() && Path.startswith("/")) - Path = Saver.save(Config->Chroot + Path); + if (!config->chroot.empty() && path.startswith("/")) + path = Saver.save(config->chroot + path); - log(Path); + log(path); - auto MBOrErr = MemoryBuffer::getFile(Path, -1, false); - if (auto EC = MBOrErr.getError()) { - error("cannot open " + Path + ": " + EC.message()); + auto mbOrErr = MemoryBuffer::getFile(path, -1, false); + if (auto ec = mbOrErr.getError()) { + error("cannot open " + path + ": " + ec.message()); return None; } - std::unique_ptr &MB = *MBOrErr; - MemoryBufferRef MBRef = MB->getMemBufferRef(); - make>(std::move(MB)); // take MB ownership - - if (Tar) - Tar->append(relativeToRoot(Path), MBRef.getBuffer()); - return MBRef; + std::unique_ptr &mb = *mbOrErr; + MemoryBufferRef mbref = mb->getMemBufferRef(); + make>(std::move(mb)); // take MB ownership + + if (tar) + tar->append(relativeToRoot(path), mbref.getBuffer()); + return mbref; } // All input object files must be for the same architecture // (e.g. it does not make sense to link x86 object files with // MIPS object files.) This function checks for that error. -static bool isCompatible(InputFile *File) { - if (!File->isElf() && !isa(File)) +static bool isCompatible(InputFile *file) { + if (!file->isElf() && !isa(file)) return true; - if (File->EKind == Config->EKind && File->EMachine == Config->EMachine) { - if (Config->EMachine != EM_MIPS) + if (file->ekind == config->ekind && file->emachine == config->emachine) { + if (config->emachine != EM_MIPS) return true; - if (isMipsN32Abi(File) == Config->MipsN32Abi) + if (isMipsN32Abi(file) == config->mipsN32Abi) return true; } - if (!Config->Emulation.empty()) { - error(toString(File) + " is incompatible with " + Config->Emulation); + if (!config->emulation.empty()) { + error(toString(file) + " is incompatible with " + config->emulation); } else { - InputFile *Existing; - if (!ObjectFiles.empty()) - Existing = ObjectFiles[0]; - else if (!SharedFiles.empty()) - Existing = SharedFiles[0]; + InputFile *existing; + if (!objectFiles.empty()) + existing = objectFiles[0]; + else if (!sharedFiles.empty()) + existing = sharedFiles[0]; else - Existing = BitcodeFiles[0]; + existing = bitcodeFiles[0]; - error(toString(File) + " is incompatible with " + toString(Existing)); + error(toString(file) + " is incompatible with " + toString(existing)); } return false; } -template static void doParseFile(InputFile *File) { - if (!isCompatible(File)) +template static void doParseFile(InputFile *file) { + if (!isCompatible(file)) return; // Binary file - if (auto *F = dyn_cast(File)) { - BinaryFiles.push_back(F); - F->parse(); + if (auto *f = dyn_cast(file)) { + binaryFiles.push_back(f); + f->parse(); return; } // .a file - if (auto *F = dyn_cast(File)) { - F->parse(); + if (auto *f = dyn_cast(file)) { + f->parse(); return; } // Lazy object file - if (auto *F = dyn_cast(File)) { - LazyObjFiles.push_back(F); - F->parse(); + if (auto *f = dyn_cast(file)) { + lazyObjFiles.push_back(f); + f->parse(); return; } - if (Config->Trace) - message(toString(File)); + if (config->trace) + message(toString(file)); // .so file - if (auto *F = dyn_cast(File)) { - F->parse(); + if (auto *f = dyn_cast(file)) { + f->parse(); return; } // LLVM bitcode file - if (auto *F = dyn_cast(File)) { - BitcodeFiles.push_back(F); - F->parse(); + if (auto *f = dyn_cast(file)) { + bitcodeFiles.push_back(f); + f->parse(); return; } // Regular object file - ObjectFiles.push_back(File); - cast>(File)->parse(); + objectFiles.push_back(file); + cast>(file)->parse(); } // Add symbols in File to the symbol table. -void elf::parseFile(InputFile *File) { - switch (Config->EKind) { +void elf::parseFile(InputFile *file) { + switch (config->ekind) { case ELF32LEKind: - doParseFile(File); + doParseFile(file); return; case ELF32BEKind: - doParseFile(File); + doParseFile(file); return; case ELF64LEKind: - doParseFile(File); + doParseFile(file); return; case ELF64BEKind: - doParseFile(File); + doParseFile(file); return; default: llvm_unreachable("unknown ELFT"); @@ -208,87 +208,87 @@ } // Concatenates arguments to construct a string representing an error location. -static std::string createFileLineMsg(StringRef Path, unsigned Line) { - std::string Filename = path::filename(Path); - std::string Lineno = ":" + std::to_string(Line); - if (Filename == Path) - return Filename + Lineno; - return Filename + Lineno + " (" + Path.str() + Lineno + ")"; +static std::string createFileLineMsg(StringRef path, unsigned line) { + std::string filename = path::filename(path); + std::string lineno = ":" + std::to_string(line); + if (filename == path) + return filename + lineno; + return filename + lineno + " (" + path.str() + lineno + ")"; } template -static std::string getSrcMsgAux(ObjFile &File, const Symbol &Sym, - InputSectionBase &Sec, uint64_t Offset) { +static std::string getSrcMsgAux(ObjFile &file, const Symbol &sym, + InputSectionBase &sec, uint64_t offset) { // In DWARF, functions and variables are stored to different places. // First, lookup a function for a given offset. - if (Optional Info = File.getDILineInfo(&Sec, Offset)) - return createFileLineMsg(Info->FileName, Info->Line); + if (Optional info = file.getDILineInfo(&sec, offset)) + return createFileLineMsg(info->FileName, info->Line); // If it failed, lookup again as a variable. - if (Optional> FileLine = - File.getVariableLoc(Sym.getName())) - return createFileLineMsg(FileLine->first, FileLine->second); + if (Optional> fileLine = + file.getVariableLoc(sym.getName())) + return createFileLineMsg(fileLine->first, fileLine->second); // File.SourceFile contains STT_FILE symbol, and that is a last resort. - return File.SourceFile; + return file.sourceFile; } -std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, - uint64_t Offset) { +std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec, + uint64_t offset) { if (kind() != ObjKind) return ""; - switch (Config->EKind) { + switch (config->ekind) { default: llvm_unreachable("Invalid kind"); case ELF32LEKind: - return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + return getSrcMsgAux(cast>(*this), sym, sec, offset); case ELF32BEKind: - return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + return getSrcMsgAux(cast>(*this), sym, sec, offset); case ELF64LEKind: - return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + return getSrcMsgAux(cast>(*this), sym, sec, offset); case ELF64BEKind: - return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + return getSrcMsgAux(cast>(*this), sym, sec, offset); } } template void ObjFile::initializeDwarf() { - Dwarf = llvm::make_unique(make_unique>(this)); - for (std::unique_ptr &CU : Dwarf->compile_units()) { - auto Report = [](Error Err) { - handleAllErrors(std::move(Err), - [](ErrorInfoBase &Info) { warn(Info.message()); }); + dwarf = llvm::make_unique(make_unique>(this)); + for (std::unique_ptr &cu : dwarf->compile_units()) { + auto report = [](Error err) { + handleAllErrors(std::move(err), + [](ErrorInfoBase &info) { warn(info.message()); }); }; - Expected ExpectedLT = - Dwarf->getLineTableForUnit(CU.get(), Report); - const DWARFDebugLine::LineTable *LT = nullptr; - if (ExpectedLT) - LT = *ExpectedLT; + Expected expectedLT = + dwarf->getLineTableForUnit(cu.get(), report); + const DWARFDebugLine::LineTable *lt = nullptr; + if (expectedLT) + lt = *expectedLT; else - Report(ExpectedLT.takeError()); - if (!LT) + report(expectedLT.takeError()); + if (!lt) continue; - LineTables.push_back(LT); + lineTables.push_back(lt); // Loop over variable records and insert them to VariableLoc. - for (const auto &Entry : CU->dies()) { - DWARFDie Die(CU.get(), &Entry); + for (const auto &entry : cu->dies()) { + DWARFDie die(cu.get(), &entry); // Skip all tags that are not variables. - if (Die.getTag() != dwarf::DW_TAG_variable) + if (die.getTag() != dwarf::DW_TAG_variable) continue; // Skip if a local variable because we don't need them for generating // error messages. In general, only non-local symbols can fail to be // linked. - if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0)) + if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0)) continue; // Get the source filename index for the variable. - unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0); - if (!LT->hasFileAtIndex(File)) + unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0); + if (!lt->hasFileAtIndex(file)) continue; // Get the line number on which the variable is declared. - unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0); + unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0); // Here we want to take the variable name to add it into VariableLoc. // Variable can have regular and linkage name associated. At first, we try @@ -296,11 +296,11 @@ // two variables in different namespaces of the same object. Use common // name otherwise, but handle the case when it also absent in case if the // input object file lacks some debug info. - StringRef Name = - dwarf::toString(Die.find(dwarf::DW_AT_linkage_name), - dwarf::toString(Die.find(dwarf::DW_AT_name), "")); - if (!Name.empty()) - VariableLoc.insert({Name, {LT, File, Line}}); + StringRef name = + dwarf::toString(die.find(dwarf::DW_AT_linkage_name), + dwarf::toString(die.find(dwarf::DW_AT_name), "")); + if (!name.empty()) + variableLoc.insert({name, {lt, file, line}}); } } } @@ -309,71 +309,71 @@ // object (variable, array, etc) definition. template Optional> -ObjFile::getVariableLoc(StringRef Name) { - llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); +ObjFile::getVariableLoc(StringRef name) { + llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); }); // Return if we have no debug information about data object. - auto It = VariableLoc.find(Name); - if (It == VariableLoc.end()) + auto it = variableLoc.find(name); + if (it == variableLoc.end()) return None; // Take file name string from line table. - std::string FileName; - if (!It->second.LT->getFileNameByIndex( - It->second.File, nullptr, - DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName)) + std::string fileName; + if (!it->second.lt->getFileNameByIndex( + it->second.file, nullptr, + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName)) return None; - return std::make_pair(FileName, It->second.Line); + return std::make_pair(fileName, it->second.line); } // Returns source line information for a given offset // using DWARF debug info. template -Optional ObjFile::getDILineInfo(InputSectionBase *S, - uint64_t Offset) { - llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); }); +Optional ObjFile::getDILineInfo(InputSectionBase *s, + uint64_t offset) { + llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); }); // Detect SectionIndex for specified section. - uint64_t SectionIndex = object::SectionedAddress::UndefSection; - ArrayRef Sections = S->File->getSections(); - for (uint64_t CurIndex = 0; CurIndex < Sections.size(); ++CurIndex) { - if (S == Sections[CurIndex]) { - SectionIndex = CurIndex; + uint64_t sectionIndex = object::SectionedAddress::UndefSection; + ArrayRef sections = s->file->getSections(); + for (uint64_t curIndex = 0; curIndex < sections.size(); ++curIndex) { + if (s == sections[curIndex]) { + sectionIndex = curIndex; break; } } // Use fake address calcuated by adding section file offset and offset in // section. See comments for ObjectInfo class. - DILineInfo Info; - for (const llvm::DWARFDebugLine::LineTable *LT : LineTables) { - if (LT->getFileLineInfoForAddress( - {S->getOffsetInFile() + Offset, SectionIndex}, nullptr, - DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info)) - return Info; + DILineInfo info; + for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) { + if (lt->getFileLineInfoForAddress( + {s->getOffsetInFile() + offset, sectionIndex}, nullptr, + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info)) + return info; } return None; } // Returns "", "foo.a(bar.o)" or "baz.o". -std::string lld::toString(const InputFile *F) { - if (!F) +std::string lld::toString(const InputFile *f) { + if (!f) return ""; - if (F->ToStringCache.empty()) { - if (F->ArchiveName.empty()) - F->ToStringCache = F->getName(); + if (f->toStringCache.empty()) { + if (f->archiveName.empty()) + f->toStringCache = f->getName(); else - F->ToStringCache = (F->ArchiveName + "(" + F->getName() + ")").str(); + f->toStringCache = (f->archiveName + "(" + f->getName() + ")").str(); } - return F->ToStringCache; + return f->toStringCache; } -ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) { - EKind = getELFKind(MB, ""); +ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) { + ekind = getELFKind(mb, ""); - switch (EKind) { + switch (ekind) { case ELF32LEKind: init(); break; @@ -392,10 +392,10 @@ } template -static const Elf_Shdr *findSection(ArrayRef Sections, uint32_t Type) { - for (const Elf_Shdr &Sec : Sections) - if (Sec.sh_type == Type) - return &Sec; +static const Elf_Shdr *findSection(ArrayRef sections, uint32_t type) { + for (const Elf_Shdr &sec : sections) + if (sec.sh_type == type) + return &sec; return nullptr; } @@ -404,57 +404,57 @@ using Elf_Sym = typename ELFT::Sym; // Initialize trivial attributes. - const ELFFile &Obj = getObj(); - EMachine = Obj.getHeader()->e_machine; - OSABI = Obj.getHeader()->e_ident[llvm::ELF::EI_OSABI]; - ABIVersion = Obj.getHeader()->e_ident[llvm::ELF::EI_ABIVERSION]; + const ELFFile &obj = getObj(); + emachine = obj.getHeader()->e_machine; + osabi = obj.getHeader()->e_ident[llvm::ELF::EI_OSABI]; + abiVersion = obj.getHeader()->e_ident[llvm::ELF::EI_ABIVERSION]; - ArrayRef Sections = CHECK(Obj.sections(), this); + ArrayRef sections = CHECK(obj.sections(), this); // Find a symbol table. - bool IsDSO = - (identify_magic(MB.getBuffer()) == file_magic::elf_shared_object); - const Elf_Shdr *SymtabSec = - findSection(Sections, IsDSO ? SHT_DYNSYM : SHT_SYMTAB); + bool isDSO = + (identify_magic(mb.getBuffer()) == file_magic::elf_shared_object); + const Elf_Shdr *symtabSec = + findSection(sections, isDSO ? SHT_DYNSYM : SHT_SYMTAB); - if (!SymtabSec) + if (!symtabSec) return; // Initialize members corresponding to a symbol table. - FirstGlobal = SymtabSec->sh_info; + firstGlobal = symtabSec->sh_info; - ArrayRef ESyms = CHECK(Obj.symbols(SymtabSec), this); - if (FirstGlobal == 0 || FirstGlobal > ESyms.size()) + ArrayRef eSyms = CHECK(obj.symbols(symtabSec), this); + if (firstGlobal == 0 || firstGlobal > eSyms.size()) fatal(toString(this) + ": invalid sh_info in symbol table"); - ELFSyms = reinterpret_cast(ESyms.data()); - NumELFSyms = ESyms.size(); - StringTable = CHECK(Obj.getStringTableForSymtab(*SymtabSec, Sections), this); + elfSyms = reinterpret_cast(eSyms.data()); + numELFSyms = eSyms.size(); + stringTable = CHECK(obj.getStringTableForSymtab(*symtabSec, sections), this); } template -uint32_t ObjFile::getSectionIndex(const Elf_Sym &Sym) const { +uint32_t ObjFile::getSectionIndex(const Elf_Sym &sym) const { return CHECK( - this->getObj().getSectionIndex(&Sym, getELFSyms(), ShndxTable), + this->getObj().getSectionIndex(&sym, getELFSyms(), shndxTable), this); } template ArrayRef ObjFile::getLocalSymbols() { - if (this->Symbols.empty()) + if (this->symbols.empty()) return {}; - return makeArrayRef(this->Symbols).slice(1, this->FirstGlobal - 1); + return makeArrayRef(this->symbols).slice(1, this->firstGlobal - 1); } template ArrayRef ObjFile::getGlobalSymbols() { - return makeArrayRef(this->Symbols).slice(this->FirstGlobal); + return makeArrayRef(this->symbols).slice(this->firstGlobal); } -template void ObjFile::parse(bool IgnoreComdats) { +template void ObjFile::parse(bool ignoreComdats) { // Read a section table. JustSymbols is usually false. - if (this->JustSymbols) + if (this->justSymbols) initializeJustSymbols(); else - initializeSections(IgnoreComdats); + initializeSections(ignoreComdats); // Read a symbol table. initializeSymbols(); @@ -464,11 +464,11 @@ // They are identified and deduplicated by group name. This function // returns a group name. template -StringRef ObjFile::getShtGroupSignature(ArrayRef Sections, - const Elf_Shdr &Sec) { - const Elf_Sym *Sym = - CHECK(object::getSymbol(this->getELFSyms(), Sec.sh_info), this); - StringRef Signature = CHECK(Sym->getName(this->StringTable), this); +StringRef ObjFile::getShtGroupSignature(ArrayRef sections, + const Elf_Shdr &sec) { + const Elf_Sym *sym = + CHECK(object::getSymbol(this->getELFSyms(), sec.sh_info), this); + StringRef signature = CHECK(sym->getName(this->stringTable), this); // As a special case, if a symbol is a section symbol and has no name, // we use a section name as a signature. @@ -477,12 +477,12 @@ // standard, but GNU gold 1.14 (the newest version as of July 2017) or // older produce such sections as outputs for the -r option, so we need // a bug-compatibility. - if (Signature.empty() && Sym->getType() == STT_SECTION) - return getSectionName(Sec); - return Signature; + if (signature.empty() && sym->getType() == STT_SECTION) + return getSectionName(sec); + return signature; } -template bool ObjFile::shouldMerge(const Elf_Shdr &Sec) { +template bool ObjFile::shouldMerge(const Elf_Shdr &sec) { // On a regular link we don't merge sections if -O0 (default is -O1). This // sometimes makes the linker significantly faster, although the output will // be bigger. @@ -495,14 +495,14 @@ // SHF_MERGE sections based both on their name and sh_entsize, but that seems // to be more trouble than it is worth. Instead, we just use the regular (-O1) // logic for -r. - if (Config->Optimize == 0 && !Config->Relocatable) + if (config->optimize == 0 && !config->relocatable) return false; // A mergeable section with size 0 is useless because they don't have // any data to merge. A mergeable string section with size 0 can be // argued as invalid because it doesn't end with a null character. // We'll avoid a mess by handling them as if they were non-mergeable. - if (Sec.sh_size == 0) + if (sec.sh_size == 0) return false; // Check for sh_entsize. The ELF spec is not clear about the zero @@ -510,17 +510,17 @@ // the section does not hold a table of fixed-size entries". We know // that Rust 1.13 produces a string mergeable section with a zero // sh_entsize. Here we just accept it rather than being picky about it. - uint64_t EntSize = Sec.sh_entsize; - if (EntSize == 0) + uint64_t entSize = sec.sh_entsize; + if (entSize == 0) return false; - if (Sec.sh_size % EntSize) + if (sec.sh_size % entSize) fatal(toString(this) + ": SHF_MERGE section size must be a multiple of sh_entsize"); - uint64_t Flags = Sec.sh_flags; - if (!(Flags & SHF_MERGE)) + uint64_t flags = sec.sh_flags; + if (!(flags & SHF_MERGE)) return false; - if (Flags & SHF_WRITE) + if (flags & SHF_WRITE) fatal(toString(this) + ": writable SHF_MERGE section is not supported"); return true; @@ -536,8 +536,8 @@ // When the option is given, we link "just symbols". The section table is // initialized with null pointers. template void ObjFile::initializeJustSymbols() { - ArrayRef Sections = CHECK(this->getObj().sections(), this); - this->Sections.resize(Sections.size()); + ArrayRef sections = CHECK(this->getObj().sections(), this); + this->sections.resize(sections.size()); } // An ELF object file may contain a `.deplibs` section. If it exists, the @@ -546,128 +546,128 @@ // the various ways that a library can be specified to LLD. This ELF extension // is a form of autolinking and is called `dependent libraries`. It is currently // unique to LLVM and lld. -static void addDependentLibrary(StringRef Specifier, const InputFile *F) { - if (!Config->DependentLibraries) +static void addDependentLibrary(StringRef specifier, const InputFile *f) { + if (!config->dependentLibraries) return; - if (fs::exists(Specifier)) - Driver->addFile(Specifier, /*WithLOption=*/false); - else if (Optional S = findFromSearchPaths(Specifier)) - Driver->addFile(*S, /*WithLOption=*/true); - else if (Optional S = searchLibraryBaseName(Specifier)) - Driver->addFile(*S, /*WithLOption=*/true); + if (fs::exists(specifier)) + driver->addFile(specifier, /*WithLOption=*/false); + else if (Optional s = findFromSearchPaths(specifier)) + driver->addFile(*s, /*WithLOption=*/true); + else if (Optional s = searchLibraryBaseName(specifier)) + driver->addFile(*s, /*WithLOption=*/true); else - error(toString(F) + + error(toString(f) + ": unable to find library from dependent library specifier: " + - Specifier); + specifier); } template -void ObjFile::initializeSections(bool IgnoreComdats) { - const ELFFile &Obj = this->getObj(); +void ObjFile::initializeSections(bool ignoreComdats) { + const ELFFile &obj = this->getObj(); - ArrayRef ObjSections = CHECK(Obj.sections(), this); - uint64_t Size = ObjSections.size(); - this->Sections.resize(Size); - this->SectionStringTable = - CHECK(Obj.getSectionStringTable(ObjSections), this); + ArrayRef objSections = CHECK(obj.sections(), this); + uint64_t size = objSections.size(); + this->sections.resize(size); + this->sectionStringTable = + CHECK(obj.getSectionStringTable(objSections), this); - for (size_t I = 0, E = ObjSections.size(); I < E; I++) { - if (this->Sections[I] == &InputSection::Discarded) + for (size_t i = 0, e = objSections.size(); i < e; i++) { + if (this->sections[i] == &InputSection::discarded) continue; - const Elf_Shdr &Sec = ObjSections[I]; + const Elf_Shdr &sec = objSections[i]; - if (Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) - CGProfile = - check(Obj.template getSectionContentsAsArray(&Sec)); + if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) + cgProfile = + check(obj.template getSectionContentsAsArray(&sec)); // SHF_EXCLUDE'ed sections are discarded by the linker. However, // if -r is given, we'll let the final link discard such sections. // This is compatible with GNU. - if ((Sec.sh_flags & SHF_EXCLUDE) && !Config->Relocatable) { - if (Sec.sh_type == SHT_LLVM_ADDRSIG) { + if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) { + if (sec.sh_type == SHT_LLVM_ADDRSIG) { // We ignore the address-significance table if we know that the object // file was created by objcopy or ld -r. This is because these tools // will reorder the symbols in the symbol table, invalidating the data // in the address-significance table, which refers to symbols by index. - if (Sec.sh_link != 0) - this->AddrsigSec = &Sec; - else if (Config->ICF == ICFLevel::Safe) + if (sec.sh_link != 0) + this->addrsigSec = &sec; + else if (config->icf == ICFLevel::Safe) warn(toString(this) + ": --icf=safe is incompatible with object " "files created using objcopy or ld -r"); } - this->Sections[I] = &InputSection::Discarded; + this->sections[i] = &InputSection::discarded; continue; } - switch (Sec.sh_type) { + switch (sec.sh_type) { case SHT_GROUP: { // De-duplicate section groups by their signatures. - StringRef Signature = getShtGroupSignature(ObjSections, Sec); - this->Sections[I] = &InputSection::Discarded; + StringRef signature = getShtGroupSignature(objSections, sec); + this->sections[i] = &InputSection::discarded; - ArrayRef Entries = - CHECK(Obj.template getSectionContentsAsArray(&Sec), this); - if (Entries.empty()) + ArrayRef entries = + CHECK(obj.template getSectionContentsAsArray(&sec), this); + if (entries.empty()) fatal(toString(this) + ": empty SHT_GROUP"); // The first word of a SHT_GROUP section contains flags. Currently, // the standard defines only "GRP_COMDAT" flag for the COMDAT group. // An group with the empty flag doesn't define anything; such sections // are just skipped. - if (Entries[0] == 0) + if (entries[0] == 0) continue; - if (Entries[0] != GRP_COMDAT) + if (entries[0] != GRP_COMDAT) fatal(toString(this) + ": unsupported SHT_GROUP format"); - bool IsNew = - IgnoreComdats || - Symtab->ComdatGroups.try_emplace(CachedHashStringRef(Signature), this) + bool isNew = + ignoreComdats || + symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this) .second; - if (IsNew) { - if (Config->Relocatable) - this->Sections[I] = createInputSection(Sec); + if (isNew) { + if (config->relocatable) + this->sections[i] = createInputSection(sec); continue; } // Otherwise, discard group members. - for (uint32_t SecIndex : Entries.slice(1)) { - if (SecIndex >= Size) + for (uint32_t secIndex : entries.slice(1)) { + if (secIndex >= size) fatal(toString(this) + - ": invalid section index in group: " + Twine(SecIndex)); - this->Sections[SecIndex] = &InputSection::Discarded; + ": invalid section index in group: " + Twine(secIndex)); + this->sections[secIndex] = &InputSection::discarded; } break; } case SHT_SYMTAB_SHNDX: - ShndxTable = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this); + shndxTable = CHECK(obj.getSHNDXTable(sec, objSections), this); break; case SHT_SYMTAB: case SHT_STRTAB: case SHT_NULL: break; default: - this->Sections[I] = createInputSection(Sec); + this->sections[i] = createInputSection(sec); } // .ARM.exidx sections have a reverse dependency on the InputSection they // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. - if (Sec.sh_flags & SHF_LINK_ORDER) { - InputSectionBase *LinkSec = nullptr; - if (Sec.sh_link < this->Sections.size()) - LinkSec = this->Sections[Sec.sh_link]; - if (!LinkSec) + if (sec.sh_flags & SHF_LINK_ORDER) { + InputSectionBase *linkSec = nullptr; + if (sec.sh_link < this->sections.size()) + linkSec = this->sections[sec.sh_link]; + if (!linkSec) fatal(toString(this) + - ": invalid sh_link index: " + Twine(Sec.sh_link)); + ": invalid sh_link index: " + Twine(sec.sh_link)); - InputSection *IS = cast(this->Sections[I]); - LinkSec->DependentSections.push_back(IS); - if (!isa(LinkSec)) - error("a section " + IS->Name + + InputSection *isec = cast(this->sections[i]); + linkSec->dependentSections.push_back(isec); + if (!isa(linkSec)) + error("a section " + isec->name + " with SHF_LINK_ORDER should not refer a non-regular " "section: " + - toString(LinkSec)); + toString(linkSec)); } } } @@ -675,9 +675,9 @@ // For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD // flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how // the input objects have been compiled. -static void updateARMVFPArgs(const ARMAttributeParser &Attributes, - const InputFile *F) { - if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args)) +static void updateARMVFPArgs(const ARMAttributeParser &attributes, + const InputFile *f) { + if (!attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args)) // If an ABI tag isn't present then it is implicitly given the value of 0 // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files, // including some in glibc that don't use FP args (and should have value 3) @@ -685,31 +685,31 @@ // as a clash. return; - unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args); - ARMVFPArgKind Arg; - switch (VFPArgs) { + unsigned vfpArgs = attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args); + ARMVFPArgKind arg; + switch (vfpArgs) { case ARMBuildAttrs::BaseAAPCS: - Arg = ARMVFPArgKind::Base; + arg = ARMVFPArgKind::Base; break; case ARMBuildAttrs::HardFPAAPCS: - Arg = ARMVFPArgKind::VFP; + arg = ARMVFPArgKind::VFP; break; case ARMBuildAttrs::ToolChainFPPCS: // Tool chain specific convention that conforms to neither AAPCS variant. - Arg = ARMVFPArgKind::ToolChain; + arg = ARMVFPArgKind::ToolChain; break; case ARMBuildAttrs::CompatibleFPAAPCS: // Object compatible with all conventions. return; default: - error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs)); + error(toString(f) + ": unknown Tag_ABI_VFP_args value: " + Twine(vfpArgs)); return; } // Follow ld.bfd and error if there is a mix of calling conventions. - if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default) - error(toString(F) + ": incompatible Tag_ABI_VFP_args"); + if (config->armVFPArgs != arg && config->armVFPArgs != ARMVFPArgKind::Default) + error(toString(f) + ": incompatible Tag_ABI_VFP_args"); else - Config->ARMVFPArgs = Arg; + config->armVFPArgs = arg; } // The ARM support in lld makes some use of instructions that are not available @@ -721,11 +721,11 @@ // at compile time. We follow the convention that if at least one input object // is compiled with an architecture that supports these features then lld is // permitted to use them. -static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) { - if (!Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) +static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) { + if (!attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) return; - auto Arch = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); - switch (Arch) { + auto arch = attributes.getAttributeValue(ARMBuildAttrs::CPU_arch); + switch (arch) { case ARMBuildAttrs::Pre_v4: case ARMBuildAttrs::v4: case ARMBuildAttrs::v4T: @@ -737,19 +737,19 @@ case ARMBuildAttrs::v6: case ARMBuildAttrs::v6KZ: case ARMBuildAttrs::v6K: - Config->ARMHasBlx = true; + config->armHasBlx = true; // Architectures used in pre-Cortex processors do not support // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do. break; default: // All other Architectures have BLX and extended branch encoding - Config->ARMHasBlx = true; - Config->ARMJ1J2BranchEncoding = true; - if (Arch != ARMBuildAttrs::v6_M && Arch != ARMBuildAttrs::v6S_M) + config->armHasBlx = true; + config->armJ1J2BranchEncoding = true; + if (arch != ARMBuildAttrs::v6_M && arch != ARMBuildAttrs::v6S_M) // All Architectures used in Cortex processors with the exception // of v6-M and v6S-M have the MOVT and MOVW instructions. - Config->ARMHasMovtMovw = true; + config->armHasMovtMovw = true; break; } } @@ -767,126 +767,126 @@ // certain type. It seems a bit too much to just store a 32-bit value, perhaps // the ABI is unnecessarily complicated. template -static uint32_t readAndFeatures(ObjFile *Obj, ArrayRef Data) { +static uint32_t readAndFeatures(ObjFile *obj, ArrayRef data) { using Elf_Nhdr = typename ELFT::Nhdr; using Elf_Note = typename ELFT::Note; - uint32_t FeaturesSet = 0; - while (!Data.empty()) { + uint32_t featuresSet = 0; + while (!data.empty()) { // Read one NOTE record. - if (Data.size() < sizeof(Elf_Nhdr)) - fatal(toString(Obj) + ": .note.gnu.property: section too short"); + if (data.size() < sizeof(Elf_Nhdr)) + fatal(toString(obj) + ": .note.gnu.property: section too short"); - auto *Nhdr = reinterpret_cast(Data.data()); - if (Data.size() < Nhdr->getSize()) - fatal(toString(Obj) + ": .note.gnu.property: section too short"); - - Elf_Note Note(*Nhdr); - if (Nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || Note.getName() != "GNU") { - Data = Data.slice(Nhdr->getSize()); + auto *nhdr = reinterpret_cast(data.data()); + if (data.size() < nhdr->getSize()) + fatal(toString(obj) + ": .note.gnu.property: section too short"); + + Elf_Note note(*nhdr); + if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") { + data = data.slice(nhdr->getSize()); continue; } - uint32_t FeatureAndType = Config->EMachine == EM_AARCH64 + uint32_t featureAndType = config->emachine == EM_AARCH64 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND : GNU_PROPERTY_X86_FEATURE_1_AND; // Read a body of a NOTE record, which consists of type-length-value fields. - ArrayRef Desc = Note.getDesc(); - while (!Desc.empty()) { - if (Desc.size() < 8) - fatal(toString(Obj) + ": .note.gnu.property: section too short"); + ArrayRef desc = note.getDesc(); + while (!desc.empty()) { + if (desc.size() < 8) + fatal(toString(obj) + ": .note.gnu.property: section too short"); - uint32_t Type = read32le(Desc.data()); - uint32_t Size = read32le(Desc.data() + 4); + uint32_t type = read32le(desc.data()); + uint32_t size = read32le(desc.data() + 4); - if (Type == FeatureAndType) { + if (type == featureAndType) { // We found a FEATURE_1_AND field. There may be more than one of these // in a .note.gnu.propery section, for a relocatable object we // accumulate the bits set. - FeaturesSet |= read32le(Desc.data() + 8); + featuresSet |= read32le(desc.data() + 8); } // On 64-bit, a payload may be followed by a 4-byte padding to make its // size a multiple of 8. if (ELFT::Is64Bits) - Size = alignTo(Size, 8); + size = alignTo(size, 8); - Desc = Desc.slice(Size + 8); // +8 for Type and Size + desc = desc.slice(size + 8); // +8 for Type and Size } // Go to next NOTE record to look for more FEATURE_1_AND descriptions. - Data = Data.slice(Nhdr->getSize()); + data = data.slice(nhdr->getSize()); } - return FeaturesSet; + return featuresSet; } template -InputSectionBase *ObjFile::getRelocTarget(const Elf_Shdr &Sec) { - uint32_t Idx = Sec.sh_info; - if (Idx >= this->Sections.size()) - fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx)); - InputSectionBase *Target = this->Sections[Idx]; +InputSectionBase *ObjFile::getRelocTarget(const Elf_Shdr &sec) { + uint32_t idx = sec.sh_info; + if (idx >= this->sections.size()) + fatal(toString(this) + ": invalid relocated section index: " + Twine(idx)); + InputSectionBase *target = this->sections[idx]; // Strictly speaking, a relocation section must be included in the // group of the section it relocates. However, LLVM 3.3 and earlier // would fail to do so, so we gracefully handle that case. - if (Target == &InputSection::Discarded) + if (target == &InputSection::discarded) return nullptr; - if (!Target) + if (!target) fatal(toString(this) + ": unsupported relocation reference"); - return Target; + return target; } // Create a regular InputSection class that has the same contents // as a given section. -static InputSection *toRegularSection(MergeInputSection *Sec) { - return make(Sec->File, Sec->Flags, Sec->Type, Sec->Alignment, - Sec->data(), Sec->Name); +static InputSection *toRegularSection(MergeInputSection *sec) { + return make(sec->file, sec->flags, sec->type, sec->alignment, + sec->data(), sec->name); } template -InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &Sec) { - StringRef Name = getSectionName(Sec); +InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &sec) { + StringRef name = getSectionName(sec); - switch (Sec.sh_type) { + switch (sec.sh_type) { case SHT_ARM_ATTRIBUTES: { - if (Config->EMachine != EM_ARM) + if (config->emachine != EM_ARM) break; - ARMAttributeParser Attributes; - ArrayRef Contents = check(this->getObj().getSectionContents(&Sec)); - Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); - updateSupportedARMFeatures(Attributes); - updateARMVFPArgs(Attributes, this); + ARMAttributeParser attributes; + ArrayRef contents = check(this->getObj().getSectionContents(&sec)); + attributes.Parse(contents, /*isLittle*/ config->ekind == ELF32LEKind); + updateSupportedARMFeatures(attributes); + updateARMVFPArgs(attributes, this); // FIXME: Retain the first attribute section we see. The eglibc ARM // dynamic loaders require the presence of an attribute section for dlopen // to work. In a full implementation we would merge all attribute sections. - if (In.ARMAttributes == nullptr) { - In.ARMAttributes = make(*this, Sec, Name); - return In.ARMAttributes; + if (in.armAttributes == nullptr) { + in.armAttributes = make(*this, sec, name); + return in.armAttributes; } - return &InputSection::Discarded; + return &InputSection::discarded; } case SHT_LLVM_DEPENDENT_LIBRARIES: { - if (Config->Relocatable) + if (config->relocatable) break; - ArrayRef Data = - CHECK(this->getObj().template getSectionContentsAsArray(&Sec), this); - if (!Data.empty() && Data.back() != '\0') { + ArrayRef data = + CHECK(this->getObj().template getSectionContentsAsArray(&sec), this); + if (!data.empty() && data.back() != '\0') { error(toString(this) + ": corrupted dependent libraries section (unterminated string): " + - Name); - return &InputSection::Discarded; + name); + return &InputSection::discarded; } - for (const char *D = Data.begin(), *E = Data.end(); D < E;) { - StringRef S(D); - addDependentLibrary(S, this); - D += S.size() + 1; + for (const char *d = data.begin(), *e = data.end(); d < e;) { + StringRef s(d); + addDependentLibrary(s, this); + d += s.size() + 1; } - return &InputSection::Discarded; + return &InputSection::discarded; } case SHT_RELA: case SHT_REL: { @@ -895,25 +895,25 @@ // and the group is discarded, even though it's a violation of the // spec. We handle that situation gracefully by discarding dangling // relocation sections. - InputSectionBase *Target = getRelocTarget(Sec); - if (!Target) + InputSectionBase *target = getRelocTarget(sec); + if (!target) return nullptr; // This section contains relocation information. // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. - if (Config->Relocatable) { - InputSection *RelocSec = make(*this, Sec, Name); + if (config->relocatable) { + InputSection *relocSec = make(*this, sec, name); // We want to add a dependency to target, similar like we do for // -emit-relocs below. This is useful for the case when linker script // contains the "/DISCARD/". It is perhaps uncommon to use a script with // -r, but we faced it in the Linux kernel and have to handle such case // and not to crash. - Target->DependentSections.push_back(RelocSec); - return RelocSec; + target->dependentSections.push_back(relocSec); + return relocSec; } - if (Target->FirstRelocation) + if (target->firstRelocation) fatal(toString(this) + ": multiple relocation sections to one section are not supported"); @@ -922,33 +922,33 @@ // because applying relocations at end of linking changes section // contents. So, we simply handle such sections as non-mergeable ones. // Degrading like this is acceptable because section merging is optional. - if (auto *MS = dyn_cast(Target)) { - Target = toRegularSection(MS); - this->Sections[Sec.sh_info] = Target; + if (auto *ms = dyn_cast(target)) { + target = toRegularSection(ms); + this->sections[sec.sh_info] = target; } - if (Sec.sh_type == SHT_RELA) { - ArrayRef Rels = CHECK(getObj().relas(&Sec), this); - Target->FirstRelocation = Rels.begin(); - Target->NumRelocations = Rels.size(); - Target->AreRelocsRela = true; + if (sec.sh_type == SHT_RELA) { + ArrayRef rels = CHECK(getObj().relas(&sec), this); + target->firstRelocation = rels.begin(); + target->numRelocations = rels.size(); + target->areRelocsRela = true; } else { - ArrayRef Rels = CHECK(getObj().rels(&Sec), this); - Target->FirstRelocation = Rels.begin(); - Target->NumRelocations = Rels.size(); - Target->AreRelocsRela = false; + ArrayRef rels = CHECK(getObj().rels(&sec), this); + target->firstRelocation = rels.begin(); + target->numRelocations = rels.size(); + target->areRelocsRela = false; } - assert(isUInt<31>(Target->NumRelocations)); + assert(isUInt<31>(target->numRelocations)); // Relocation sections processed by the linker are usually removed // from the output, so returning `nullptr` for the normal case. // However, if -emit-relocs is given, we need to leave them in the output. // (Some post link analysis tools need this information.) - if (Config->EmitRelocs) { - InputSection *RelocSec = make(*this, Sec, Name); + if (config->emitRelocs) { + InputSection *relocSec = make(*this, sec, name); // We will not emit relocation section if target was discarded. - Target->DependentSections.push_back(RelocSec); - return RelocSec; + target->dependentSections.push_back(relocSec); + return relocSec; } return nullptr; } @@ -967,8 +967,8 @@ // explicitly told to do otherwise (by -z execstack). Because the stack // executable-ness is controlled solely by command line options, // .note.GNU-stack sections are simply ignored. - if (Name == ".note.GNU-stack") - return &InputSection::Discarded; + if (name == ".note.GNU-stack") + return &InputSection::discarded; // Object files that use processor features such as Intel Control-Flow // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a @@ -978,31 +978,31 @@ // Since we merge bitmaps from multiple object files to create a new // .note.gnu.property containing a single AND'ed bitmap, we discard an input // file's .note.gnu.property section. - if (Name == ".note.gnu.property") { - ArrayRef Contents = check(this->getObj().getSectionContents(&Sec)); - this->AndFeatures = readAndFeatures(this, Contents); - return &InputSection::Discarded; + if (name == ".note.gnu.property") { + ArrayRef contents = check(this->getObj().getSectionContents(&sec)); + this->andFeatures = readAndFeatures(this, contents); + return &InputSection::discarded; } // Split stacks is a feature to support a discontiguous stack, // commonly used in the programming language Go. For the details, // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled // for split stack will include a .note.GNU-split-stack section. - if (Name == ".note.GNU-split-stack") { - if (Config->Relocatable) { + if (name == ".note.GNU-split-stack") { + if (config->relocatable) { error("cannot mix split-stack and non-split-stack in a relocatable link"); - return &InputSection::Discarded; + return &InputSection::discarded; } - this->SplitStack = true; - return &InputSection::Discarded; + this->splitStack = true; + return &InputSection::discarded; } // An object file cmpiled for split stack, but where some of the // functions were compiled with the no_split_stack_attribute will // include a .note.GNU-no-split-stack section. - if (Name == ".note.GNU-no-split-stack") { - this->SomeNoSplitStack = true; - return &InputSection::Discarded; + if (name == ".note.GNU-no-split-stack") { + this->someNoSplitStack = true; + return &InputSection::discarded; } // The linkonce feature is a sort of proto-comdat. Some glibc i386 object @@ -1010,98 +1010,98 @@ // sections. Drop those sections to avoid duplicate symbol errors. // FIXME: This is glibc PR20543, we should remove this hack once that has been // fixed for a while. - if (Name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" || - Name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx") - return &InputSection::Discarded; + if (name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" || + name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx") + return &InputSection::discarded; // If we are creating a new .build-id section, strip existing .build-id // sections so that the output won't have more than one .build-id. // This is not usually a problem because input object files normally don't // have .build-id sections, but you can create such files by // "ld.{bfd,gold,lld} -r --build-id", and we want to guard against it. - if (Name == ".note.gnu.build-id" && Config->BuildId != BuildIdKind::None) - return &InputSection::Discarded; + if (name == ".note.gnu.build-id" && config->buildId != BuildIdKind::None) + return &InputSection::discarded; // The linker merges EH (exception handling) frames and creates a // .eh_frame_hdr section for runtime. So we handle them with a special // class. For relocatable outputs, they are just passed through. - if (Name == ".eh_frame" && !Config->Relocatable) - return make(*this, Sec, Name); + if (name == ".eh_frame" && !config->relocatable) + return make(*this, sec, name); - if (shouldMerge(Sec)) - return make(*this, Sec, Name); - return make(*this, Sec, Name); + if (shouldMerge(sec)) + return make(*this, sec, name); + return make(*this, sec, name); } template -StringRef ObjFile::getSectionName(const Elf_Shdr &Sec) { - return CHECK(getObj().getSectionName(&Sec, SectionStringTable), this); +StringRef ObjFile::getSectionName(const Elf_Shdr &sec) { + return CHECK(getObj().getSectionName(&sec, sectionStringTable), this); } // Initialize this->Symbols. this->Symbols is a parallel array as // its corresponding ELF symbol table. template void ObjFile::initializeSymbols() { - ArrayRef ESyms = this->getELFSyms(); - this->Symbols.resize(ESyms.size()); + ArrayRef eSyms = this->getELFSyms(); + this->symbols.resize(eSyms.size()); // Our symbol table may have already been partially initialized // because of LazyObjFile. - for (size_t I = 0, End = ESyms.size(); I != End; ++I) - if (!this->Symbols[I] && ESyms[I].getBinding() != STB_LOCAL) - this->Symbols[I] = - Symtab->insert(CHECK(ESyms[I].getName(this->StringTable), this)); + for (size_t i = 0, end = eSyms.size(); i != end; ++i) + if (!this->symbols[i] && eSyms[i].getBinding() != STB_LOCAL) + this->symbols[i] = + symtab->insert(CHECK(eSyms[i].getName(this->stringTable), this)); // Fill this->Symbols. A symbol is either local or global. - for (size_t I = 0, End = ESyms.size(); I != End; ++I) { - const Elf_Sym &ESym = ESyms[I]; + for (size_t i = 0, end = eSyms.size(); i != end; ++i) { + const Elf_Sym &eSym = eSyms[i]; // Read symbol attributes. - uint32_t SecIdx = getSectionIndex(ESym); - if (SecIdx >= this->Sections.size()) - fatal(toString(this) + ": invalid section index: " + Twine(SecIdx)); - - InputSectionBase *Sec = this->Sections[SecIdx]; - uint8_t Binding = ESym.getBinding(); - uint8_t StOther = ESym.st_other; - uint8_t Type = ESym.getType(); - uint64_t Value = ESym.st_value; - uint64_t Size = ESym.st_size; - StringRefZ Name = this->StringTable.data() + ESym.st_name; + uint32_t secIdx = getSectionIndex(eSym); + if (secIdx >= this->sections.size()) + fatal(toString(this) + ": invalid section index: " + Twine(secIdx)); + + InputSectionBase *sec = this->sections[secIdx]; + uint8_t binding = eSym.getBinding(); + uint8_t stOther = eSym.st_other; + uint8_t type = eSym.getType(); + uint64_t value = eSym.st_value; + uint64_t size = eSym.st_size; + StringRefZ name = this->stringTable.data() + eSym.st_name; // Handle local symbols. Local symbols are not added to the symbol // table because they are not visible from other object files. We // allocate symbol instances and add their pointers to Symbols. - if (Binding == STB_LOCAL) { - if (ESym.getType() == STT_FILE) - SourceFile = CHECK(ESym.getName(this->StringTable), this); + if (binding == STB_LOCAL) { + if (eSym.getType() == STT_FILE) + sourceFile = CHECK(eSym.getName(this->stringTable), this); - if (this->StringTable.size() <= ESym.st_name) + if (this->stringTable.size() <= eSym.st_name) fatal(toString(this) + ": invalid symbol name offset"); - if (ESym.st_shndx == SHN_UNDEF) - this->Symbols[I] = make(this, Name, Binding, StOther, Type); - else if (Sec == &InputSection::Discarded) - this->Symbols[I] = make(this, Name, Binding, StOther, Type, - /*DiscardedSecIdx=*/SecIdx); + if (eSym.st_shndx == SHN_UNDEF) + this->symbols[i] = make(this, name, binding, stOther, type); + else if (sec == &InputSection::discarded) + this->symbols[i] = make(this, name, binding, stOther, type, + /*DiscardedSecIdx=*/secIdx); else - this->Symbols[I] = - make(this, Name, Binding, StOther, Type, Value, Size, Sec); + this->symbols[i] = + make(this, name, binding, stOther, type, value, size, sec); continue; } // Handle global undefined symbols. - if (ESym.st_shndx == SHN_UNDEF) { - this->Symbols[I]->resolve(Undefined{this, Name, Binding, StOther, Type}); + if (eSym.st_shndx == SHN_UNDEF) { + this->symbols[i]->resolve(Undefined{this, name, binding, stOther, type}); continue; } // Handle global common symbols. - if (ESym.st_shndx == SHN_COMMON) { - if (Value == 0 || Value >= UINT32_MAX) - fatal(toString(this) + ": common symbol '" + StringRef(Name.Data) + - "' has invalid alignment: " + Twine(Value)); - this->Symbols[I]->resolve( - CommonSymbol{this, Name, Binding, StOther, Type, Value, Size}); + if (eSym.st_shndx == SHN_COMMON) { + if (value == 0 || value >= UINT32_MAX) + fatal(toString(this) + ": common symbol '" + StringRef(name.data) + + "' has invalid alignment: " + Twine(value)); + this->symbols[i]->resolve( + CommonSymbol{this, name, binding, stOther, type, value, size}); continue; } @@ -1110,87 +1110,87 @@ // standard, but in practice, a .eh_frame often directly refer // COMDAT member sections, and if a comdat group is discarded, some // defined symbol in a .eh_frame becomes dangling symbols. - if (Sec == &InputSection::Discarded) { - this->Symbols[I]->resolve( - Undefined{this, Name, Binding, StOther, Type, SecIdx}); + if (sec == &InputSection::discarded) { + this->symbols[i]->resolve( + Undefined{this, name, binding, stOther, type, secIdx}); continue; } // Handle global defined symbols. - if (Binding == STB_GLOBAL || Binding == STB_WEAK || - Binding == STB_GNU_UNIQUE) { - this->Symbols[I]->resolve( - Defined{this, Name, Binding, StOther, Type, Value, Size, Sec}); + if (binding == STB_GLOBAL || binding == STB_WEAK || + binding == STB_GNU_UNIQUE) { + this->symbols[i]->resolve( + Defined{this, name, binding, stOther, type, value, size, sec}); continue; } - fatal(toString(this) + ": unexpected binding: " + Twine((int)Binding)); + fatal(toString(this) + ": unexpected binding: " + Twine((int)binding)); } } -ArchiveFile::ArchiveFile(std::unique_ptr &&File) - : InputFile(ArchiveKind, File->getMemoryBufferRef()), - File(std::move(File)) {} +ArchiveFile::ArchiveFile(std::unique_ptr &&file) + : InputFile(ArchiveKind, file->getMemoryBufferRef()), + file(std::move(file)) {} void ArchiveFile::parse() { - for (const Archive::Symbol &Sym : File->symbols()) - Symtab->addSymbol(LazyArchive{*this, Sym}); + for (const Archive::Symbol &sym : file->symbols()) + symtab->addSymbol(LazyArchive{*this, sym}); } // Returns a buffer pointing to a member file containing a given symbol. -void ArchiveFile::fetch(const Archive::Symbol &Sym) { - Archive::Child C = - CHECK(Sym.getMember(), toString(this) + +void ArchiveFile::fetch(const Archive::Symbol &sym) { + Archive::Child c = + CHECK(sym.getMember(), toString(this) + ": could not get the member for symbol " + - Sym.getName()); + sym.getName()); - if (!Seen.insert(C.getChildOffset()).second) + if (!seen.insert(c.getChildOffset()).second) return; - MemoryBufferRef MB = - CHECK(C.getMemoryBufferRef(), + MemoryBufferRef mb = + CHECK(c.getMemoryBufferRef(), toString(this) + ": could not get the buffer for the member defining symbol " + - Sym.getName()); + sym.getName()); - if (Tar && C.getParent()->isThin()) - Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), MB.getBuffer()); + if (tar && c.getParent()->isThin()) + tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer()); - InputFile *File = createObjectFile( - MB, getName(), C.getParent()->isThin() ? 0 : C.getChildOffset()); - File->GroupId = GroupId; - parseFile(File); + InputFile *file = createObjectFile( + mb, getName(), c.getParent()->isThin() ? 0 : c.getChildOffset()); + file->groupId = groupId; + parseFile(file); } -unsigned SharedFile::VernauxNum; +unsigned SharedFile::vernauxNum; // Parse the version definitions in the object file if present, and return a // vector whose nth element contains a pointer to the Elf_Verdef for version // identifier n. Version identifiers that are not definitions map to nullptr. template -static std::vector parseVerdefs(const uint8_t *Base, - const typename ELFT::Shdr *Sec) { - if (!Sec) +static std::vector parseVerdefs(const uint8_t *base, + const typename ELFT::Shdr *sec) { + if (!sec) return {}; // We cannot determine the largest verdef identifier without inspecting // every Elf_Verdef, but both bfd and gold assign verdef identifiers // sequentially starting from 1, so we predict that the largest identifier // will be VerdefCount. - unsigned VerdefCount = Sec->sh_info; - std::vector Verdefs(VerdefCount + 1); + unsigned verdefCount = sec->sh_info; + std::vector verdefs(verdefCount + 1); // Build the Verdefs array by following the chain of Elf_Verdef objects // from the start of the .gnu.version_d section. - const uint8_t *Verdef = Base + Sec->sh_offset; - for (unsigned I = 0; I != VerdefCount; ++I) { - auto *CurVerdef = reinterpret_cast(Verdef); - Verdef += CurVerdef->vd_next; - unsigned VerdefIndex = CurVerdef->vd_ndx; - Verdefs.resize(VerdefIndex + 1); - Verdefs[VerdefIndex] = CurVerdef; + const uint8_t *verdef = base + sec->sh_offset; + for (unsigned i = 0; i != verdefCount; ++i) { + auto *curVerdef = reinterpret_cast(verdef); + verdef += curVerdef->vd_next; + unsigned verdefIndex = curVerdef->vd_ndx; + verdefs.resize(verdefIndex + 1); + verdefs[verdefIndex] = curVerdef; } - return Verdefs; + return verdefs; } // We do not usually care about alignments of data in shared object @@ -1198,14 +1198,14 @@ // DSO symbol to point to .bss due to copy relocation, we need to keep // the original alignment requirements. We infer it in this function. template -static uint64_t getAlignment(ArrayRef Sections, - const typename ELFT::Sym &Sym) { - uint64_t Ret = UINT64_MAX; - if (Sym.st_value) - Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); - if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) - Ret = std::min(Ret, Sections[Sym.st_shndx].sh_addralign); - return (Ret > UINT32_MAX) ? 0 : Ret; +static uint64_t getAlignment(ArrayRef sections, + const typename ELFT::Sym &sym) { + uint64_t ret = UINT64_MAX; + if (sym.st_value) + ret = 1ULL << countTrailingZeros((uint64_t)sym.st_value); + if (0 < sym.st_shndx && sym.st_shndx < sections.size()) + ret = std::min(ret, sections[sym.st_shndx].sh_addralign); + return (ret > UINT32_MAX) ? 0 : ret; } // Fully parse the shared object file. @@ -1230,156 +1230,156 @@ using Elf_Verdef = typename ELFT::Verdef; using Elf_Versym = typename ELFT::Versym; - ArrayRef DynamicTags; - const ELFFile Obj = this->getObj(); - ArrayRef Sections = CHECK(Obj.sections(), this); + ArrayRef dynamicTags; + const ELFFile obj = this->getObj(); + ArrayRef sections = CHECK(obj.sections(), this); - const Elf_Shdr *VersymSec = nullptr; - const Elf_Shdr *VerdefSec = nullptr; + const Elf_Shdr *versymSec = nullptr; + const Elf_Shdr *verdefSec = nullptr; // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d. - for (const Elf_Shdr &Sec : Sections) { - switch (Sec.sh_type) { + for (const Elf_Shdr &sec : sections) { + switch (sec.sh_type) { default: continue; case SHT_DYNAMIC: - DynamicTags = - CHECK(Obj.template getSectionContentsAsArray(&Sec), this); + dynamicTags = + CHECK(obj.template getSectionContentsAsArray(&sec), this); break; case SHT_GNU_versym: - VersymSec = &Sec; + versymSec = &sec; break; case SHT_GNU_verdef: - VerdefSec = &Sec; + verdefSec = &sec; break; } } - if (VersymSec && NumELFSyms == 0) { + if (versymSec && numELFSyms == 0) { error("SHT_GNU_versym should be associated with symbol table"); return; } // Search for a DT_SONAME tag to initialize this->SoName. - for (const Elf_Dyn &Dyn : DynamicTags) { - if (Dyn.d_tag == DT_NEEDED) { - uint64_t Val = Dyn.getVal(); - if (Val >= this->StringTable.size()) + for (const Elf_Dyn &dyn : dynamicTags) { + if (dyn.d_tag == DT_NEEDED) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) fatal(toString(this) + ": invalid DT_NEEDED entry"); - DtNeeded.push_back(this->StringTable.data() + Val); - } else if (Dyn.d_tag == DT_SONAME) { - uint64_t Val = Dyn.getVal(); - if (Val >= this->StringTable.size()) + dtNeeded.push_back(this->stringTable.data() + val); + } else if (dyn.d_tag == DT_SONAME) { + uint64_t val = dyn.getVal(); + if (val >= this->stringTable.size()) fatal(toString(this) + ": invalid DT_SONAME entry"); - SoName = this->StringTable.data() + Val; + soName = this->stringTable.data() + val; } } // DSOs are uniquified not by filename but by soname. - DenseMap::iterator It; - bool WasInserted; - std::tie(It, WasInserted) = Symtab->SoNames.try_emplace(SoName, this); + DenseMap::iterator it; + bool wasInserted; + std::tie(it, wasInserted) = symtab->soNames.try_emplace(soName, this); // If a DSO appears more than once on the command line with and without // --as-needed, --no-as-needed takes precedence over --as-needed because a // user can add an extra DSO with --no-as-needed to force it to be added to // the dependency list. - It->second->IsNeeded |= IsNeeded; - if (!WasInserted) + it->second->isNeeded |= isNeeded; + if (!wasInserted) return; - SharedFiles.push_back(this); + sharedFiles.push_back(this); - Verdefs = parseVerdefs(Obj.base(), VerdefSec); + verdefs = parseVerdefs(obj.base(), verdefSec); // Parse ".gnu.version" section which is a parallel array for the symbol // table. If a given file doesn't have a ".gnu.version" section, we use // VER_NDX_GLOBAL. - size_t Size = NumELFSyms - FirstGlobal; - std::vector Versyms(Size, VER_NDX_GLOBAL); - if (VersymSec) { - ArrayRef Versym = - CHECK(Obj.template getSectionContentsAsArray(VersymSec), + size_t size = numELFSyms - firstGlobal; + std::vector versyms(size, VER_NDX_GLOBAL); + if (versymSec) { + ArrayRef versym = + CHECK(obj.template getSectionContentsAsArray(versymSec), this) - .slice(FirstGlobal); - for (size_t I = 0; I < Size; ++I) - Versyms[I] = Versym[I].vs_index; + .slice(firstGlobal); + for (size_t i = 0; i < size; ++i) + versyms[i] = versym[i].vs_index; } // System libraries can have a lot of symbols with versions. Using a // fixed buffer for computing the versions name (foo@ver) can save a // lot of allocations. - SmallString<0> VersionedNameBuffer; + SmallString<0> versionedNameBuffer; // Add symbols to the symbol table. - ArrayRef Syms = this->getGlobalELFSyms(); - for (size_t I = 0; I < Syms.size(); ++I) { - const Elf_Sym &Sym = Syms[I]; + ArrayRef syms = this->getGlobalELFSyms(); + for (size_t i = 0; i < syms.size(); ++i) { + const Elf_Sym &sym = syms[i]; // ELF spec requires that all local symbols precede weak or global // symbols in each symbol table, and the index of first non-local symbol // is stored to sh_info. If a local symbol appears after some non-local // symbol, that's a violation of the spec. - StringRef Name = CHECK(Sym.getName(this->StringTable), this); - if (Sym.getBinding() == STB_LOCAL) { - warn("found local symbol '" + Name + + StringRef name = CHECK(sym.getName(this->stringTable), this); + if (sym.getBinding() == STB_LOCAL) { + warn("found local symbol '" + name + "' in global part of symbol table in file " + toString(this)); continue; } - if (Sym.isUndefined()) { - Symbol *S = Symtab->addSymbol( - Undefined{this, Name, Sym.getBinding(), Sym.st_other, Sym.getType()}); - S->ExportDynamic = true; + if (sym.isUndefined()) { + Symbol *s = symtab->addSymbol( + Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); + s->exportDynamic = true; continue; } // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly // assigns VER_NDX_LOCAL to this section global symbol. Here is a // workaround for this bug. - uint32_t Idx = Versyms[I] & ~VERSYM_HIDDEN; - if (Config->EMachine == EM_MIPS && Idx == VER_NDX_LOCAL && - Name == "_gp_disp") + uint32_t idx = versyms[i] & ~VERSYM_HIDDEN; + if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL && + name == "_gp_disp") continue; - uint32_t Alignment = getAlignment(Sections, Sym); - if (!(Versyms[I] & VERSYM_HIDDEN)) { - Symtab->addSymbol(SharedSymbol{*this, Name, Sym.getBinding(), - Sym.st_other, Sym.getType(), Sym.st_value, - Sym.st_size, Alignment, Idx}); + uint32_t alignment = getAlignment(sections, sym); + if (!(versyms[i] & VERSYM_HIDDEN)) { + symtab->addSymbol(SharedSymbol{*this, name, sym.getBinding(), + sym.st_other, sym.getType(), sym.st_value, + sym.st_size, alignment, idx}); } // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. - if (Idx == VER_NDX_GLOBAL) + if (idx == VER_NDX_GLOBAL) continue; - if (Idx >= Verdefs.size() || Idx == VER_NDX_LOCAL) { - error("corrupt input file: version definition index " + Twine(Idx) + - " for symbol " + Name + " is out of bounds\n>>> defined in " + + if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) { + error("corrupt input file: version definition index " + Twine(idx) + + " for symbol " + name + " is out of bounds\n>>> defined in " + toString(this)); continue; } - StringRef VerName = - this->StringTable.data() + - reinterpret_cast(Verdefs[Idx])->getAux()->vda_name; - VersionedNameBuffer.clear(); - Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer); - Symtab->addSymbol(SharedSymbol{*this, Saver.save(Name), Sym.getBinding(), - Sym.st_other, Sym.getType(), Sym.st_value, - Sym.st_size, Alignment, Idx}); + StringRef verName = + this->stringTable.data() + + reinterpret_cast(verdefs[idx])->getAux()->vda_name; + versionedNameBuffer.clear(); + name = (name + "@" + verName).toStringRef(versionedNameBuffer); + symtab->addSymbol(SharedSymbol{*this, Saver.save(name), sym.getBinding(), + sym.st_other, sym.getType(), sym.st_value, + sym.st_size, alignment, idx}); } } -static ELFKind getBitcodeELFKind(const Triple &T) { - if (T.isLittleEndian()) - return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind; - return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind; +static ELFKind getBitcodeELFKind(const Triple &t) { + if (t.isLittleEndian()) + return t.isArch64Bit() ? ELF64LEKind : ELF32LEKind; + return t.isArch64Bit() ? ELF64BEKind : ELF32BEKind; } -static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) { - switch (T.getArch()) { +static uint8_t getBitcodeMachineKind(StringRef path, const Triple &t) { + switch (t.getArch()) { case Triple::aarch64: return EM_AARCH64; case Triple::amdgcn: @@ -1406,24 +1406,24 @@ case Triple::riscv64: return EM_RISCV; case Triple::x86: - return T.isOSIAMCU() ? EM_IAMCU : EM_386; + return t.isOSIAMCU() ? EM_IAMCU : EM_386; case Triple::x86_64: return EM_X86_64; default: - error(Path + ": could not infer e_machine from bitcode target triple " + - T.str()); + error(path + ": could not infer e_machine from bitcode target triple " + + t.str()); return EM_NONE; } } -BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName, - uint64_t OffsetInArchive) - : InputFile(BitcodeKind, MB) { - this->ArchiveName = ArchiveName; - - std::string Path = MB.getBufferIdentifier().str(); - if (Config->ThinLTOIndexOnly) - Path = replaceThinLTOSuffix(MB.getBufferIdentifier()); +BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName, + uint64_t offsetInArchive) + : InputFile(BitcodeKind, mb) { + this->archiveName = archiveName; + + std::string path = mb.getBufferIdentifier().str(); + if (config->thinLTOIndexOnly) + path = replaceThinLTOSuffix(mb.getBufferIdentifier()); // ThinLTO assumes that all MemoryBufferRefs given to it have a unique // name. If two archives define two members with the same name, this @@ -1431,21 +1431,21 @@ // into consideration at LTO time (which very likely causes undefined // symbols later in the link stage). So we append file offset to make // filename unique. - StringRef Name = ArchiveName.empty() - ? Saver.save(Path) - : Saver.save(ArchiveName + "(" + Path + " at " + - utostr(OffsetInArchive) + ")"); - MemoryBufferRef MBRef(MB.getBuffer(), Name); + StringRef name = archiveName.empty() + ? Saver.save(path) + : Saver.save(archiveName + "(" + path + " at " + + utostr(offsetInArchive) + ")"); + MemoryBufferRef mbref(mb.getBuffer(), name); - Obj = CHECK(lto::InputFile::create(MBRef), this); + obj = CHECK(lto::InputFile::create(mbref), this); - Triple T(Obj->getTargetTriple()); - EKind = getBitcodeELFKind(T); - EMachine = getBitcodeMachineKind(MB.getBufferIdentifier(), T); + Triple t(obj->getTargetTriple()); + ekind = getBitcodeELFKind(t); + emachine = getBitcodeMachineKind(mb.getBufferIdentifier(), t); } -static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) { - switch (GvVisibility) { +static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) { + switch (gvVisibility) { case GlobalValue::DefaultVisibility: return STV_DEFAULT; case GlobalValue::HiddenVisibility: @@ -1457,169 +1457,169 @@ } template -static Symbol *createBitcodeSymbol(const std::vector &KeptComdats, - const lto::InputFile::Symbol &ObjSym, - BitcodeFile &F) { - StringRef Name = Saver.save(ObjSym.getName()); - uint8_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL; - uint8_t Type = ObjSym.isTLS() ? STT_TLS : STT_NOTYPE; - uint8_t Visibility = mapVisibility(ObjSym.getVisibility()); - bool CanOmitFromDynSym = ObjSym.canBeOmittedFromSymbolTable(); - - int C = ObjSym.getComdatIndex(); - if (ObjSym.isUndefined() || (C != -1 && !KeptComdats[C])) { - Undefined New(&F, Name, Binding, Visibility, Type); - if (CanOmitFromDynSym) - New.ExportDynamic = false; - return Symtab->addSymbol(New); - } - - if (ObjSym.isCommon()) - return Symtab->addSymbol( - CommonSymbol{&F, Name, Binding, Visibility, STT_OBJECT, - ObjSym.getCommonAlignment(), ObjSym.getCommonSize()}); - - Defined New(&F, Name, Binding, Visibility, Type, 0, 0, nullptr); - if (CanOmitFromDynSym) - New.ExportDynamic = false; - return Symtab->addSymbol(New); +static Symbol *createBitcodeSymbol(const std::vector &keptComdats, + const lto::InputFile::Symbol &objSym, + BitcodeFile &f) { + StringRef name = Saver.save(objSym.getName()); + uint8_t binding = objSym.isWeak() ? STB_WEAK : STB_GLOBAL; + uint8_t type = objSym.isTLS() ? STT_TLS : STT_NOTYPE; + uint8_t visibility = mapVisibility(objSym.getVisibility()); + bool canOmitFromDynSym = objSym.canBeOmittedFromSymbolTable(); + + int c = objSym.getComdatIndex(); + if (objSym.isUndefined() || (c != -1 && !keptComdats[c])) { + Undefined New(&f, name, binding, visibility, type); + if (canOmitFromDynSym) + New.exportDynamic = false; + return symtab->addSymbol(New); + } + + if (objSym.isCommon()) + return symtab->addSymbol( + CommonSymbol{&f, name, binding, visibility, STT_OBJECT, + objSym.getCommonAlignment(), objSym.getCommonSize()}); + + Defined New(&f, name, binding, visibility, type, 0, 0, nullptr); + if (canOmitFromDynSym) + New.exportDynamic = false; + return symtab->addSymbol(New); } template void BitcodeFile::parse() { - std::vector KeptComdats; - for (StringRef S : Obj->getComdatTable()) - KeptComdats.push_back( - Symtab->ComdatGroups.try_emplace(CachedHashStringRef(S), this).second); + std::vector keptComdats; + for (StringRef s : obj->getComdatTable()) + keptComdats.push_back( + symtab->comdatGroups.try_emplace(CachedHashStringRef(s), this).second); - for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) - Symbols.push_back(createBitcodeSymbol(KeptComdats, ObjSym, *this)); + for (const lto::InputFile::Symbol &objSym : obj->symbols()) + symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this)); - for (auto L : Obj->getDependentLibraries()) - addDependentLibrary(L, this); + for (auto l : obj->getDependentLibraries()) + addDependentLibrary(l, this); } void BinaryFile::parse() { - ArrayRef Data = arrayRefFromStringRef(MB.getBuffer()); - auto *Section = make(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, - 8, Data, ".data"); - Sections.push_back(Section); + ArrayRef data = arrayRefFromStringRef(mb.getBuffer()); + auto *section = make(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, + 8, data, ".data"); + sections.push_back(section); // For each input file foo that is embedded to a result as a binary // blob, we define _binary_foo_{start,end,size} symbols, so that // user programs can access blobs by name. Non-alphanumeric // characters in a filename are replaced with underscore. - std::string S = "_binary_" + MB.getBufferIdentifier().str(); - for (size_t I = 0; I < S.size(); ++I) - if (!isAlnum(S[I])) - S[I] = '_'; - - Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_start"), STB_GLOBAL, - STV_DEFAULT, STT_OBJECT, 0, 0, Section}); - Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_end"), STB_GLOBAL, - STV_DEFAULT, STT_OBJECT, Data.size(), 0, Section}); - Symtab->addSymbol(Defined{nullptr, Saver.save(S + "_size"), STB_GLOBAL, - STV_DEFAULT, STT_OBJECT, Data.size(), 0, nullptr}); -} - -InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, - uint64_t OffsetInArchive) { - if (isBitcode(MB)) - return make(MB, ArchiveName, OffsetInArchive); + std::string s = "_binary_" + mb.getBufferIdentifier().str(); + for (size_t i = 0; i < s.size(); ++i) + if (!isAlnum(s[i])) + s[i] = '_'; + + symtab->addSymbol(Defined{nullptr, Saver.save(s + "_start"), STB_GLOBAL, + STV_DEFAULT, STT_OBJECT, 0, 0, section}); + symtab->addSymbol(Defined{nullptr, Saver.save(s + "_end"), STB_GLOBAL, + STV_DEFAULT, STT_OBJECT, data.size(), 0, section}); + symtab->addSymbol(Defined{nullptr, Saver.save(s + "_size"), STB_GLOBAL, + STV_DEFAULT, STT_OBJECT, data.size(), 0, nullptr}); +} + +InputFile *elf::createObjectFile(MemoryBufferRef mb, StringRef archiveName, + uint64_t offsetInArchive) { + if (isBitcode(mb)) + return make(mb, archiveName, offsetInArchive); - switch (getELFKind(MB, ArchiveName)) { + switch (getELFKind(mb, archiveName)) { case ELF32LEKind: - return make>(MB, ArchiveName); + return make>(mb, archiveName); case ELF32BEKind: - return make>(MB, ArchiveName); + return make>(mb, archiveName); case ELF64LEKind: - return make>(MB, ArchiveName); + return make>(mb, archiveName); case ELF64BEKind: - return make>(MB, ArchiveName); + return make>(mb, archiveName); default: llvm_unreachable("getELFKind"); } } void LazyObjFile::fetch() { - if (MB.getBuffer().empty()) + if (mb.getBuffer().empty()) return; - InputFile *File = createObjectFile(MB, ArchiveName, OffsetInArchive); - File->GroupId = GroupId; + InputFile *file = createObjectFile(mb, archiveName, offsetInArchive); + file->groupId = groupId; - MB = {}; + mb = {}; // Copy symbol vector so that the new InputFile doesn't have to // insert the same defined symbols to the symbol table again. - File->Symbols = std::move(Symbols); + file->symbols = std::move(symbols); - parseFile(File); + parseFile(file); } template void LazyObjFile::parse() { using Elf_Sym = typename ELFT::Sym; // A lazy object file wraps either a bitcode file or an ELF file. - if (isBitcode(this->MB)) { - std::unique_ptr Obj = - CHECK(lto::InputFile::create(this->MB), this); - for (const lto::InputFile::Symbol &Sym : Obj->symbols()) { - if (Sym.isUndefined()) + if (isBitcode(this->mb)) { + std::unique_ptr obj = + CHECK(lto::InputFile::create(this->mb), this); + for (const lto::InputFile::Symbol &sym : obj->symbols()) { + if (sym.isUndefined()) continue; - Symtab->addSymbol(LazyObject{*this, Saver.save(Sym.getName())}); + symtab->addSymbol(LazyObject{*this, Saver.save(sym.getName())}); } return; } - if (getELFKind(this->MB, ArchiveName) != Config->EKind) { - error("incompatible file: " + this->MB.getBufferIdentifier()); + if (getELFKind(this->mb, archiveName) != config->ekind) { + error("incompatible file: " + this->mb.getBufferIdentifier()); return; } // Find a symbol table. - ELFFile Obj = check(ELFFile::create(MB.getBuffer())); - ArrayRef Sections = CHECK(Obj.sections(), this); + ELFFile obj = check(ELFFile::create(mb.getBuffer())); + ArrayRef sections = CHECK(obj.sections(), this); - for (const typename ELFT::Shdr &Sec : Sections) { - if (Sec.sh_type != SHT_SYMTAB) + for (const typename ELFT::Shdr &sec : sections) { + if (sec.sh_type != SHT_SYMTAB) continue; // A symbol table is found. - ArrayRef ESyms = CHECK(Obj.symbols(&Sec), this); - uint32_t FirstGlobal = Sec.sh_info; - StringRef Strtab = CHECK(Obj.getStringTableForSymtab(Sec, Sections), this); - this->Symbols.resize(ESyms.size()); + ArrayRef eSyms = CHECK(obj.symbols(&sec), this); + uint32_t firstGlobal = sec.sh_info; + StringRef strtab = CHECK(obj.getStringTableForSymtab(sec, sections), this); + this->symbols.resize(eSyms.size()); // Get existing symbols or insert placeholder symbols. - for (size_t I = FirstGlobal, End = ESyms.size(); I != End; ++I) - if (ESyms[I].st_shndx != SHN_UNDEF) - this->Symbols[I] = Symtab->insert(CHECK(ESyms[I].getName(Strtab), this)); + for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i) + if (eSyms[i].st_shndx != SHN_UNDEF) + this->symbols[i] = symtab->insert(CHECK(eSyms[i].getName(strtab), this)); // Replace existing symbols with LazyObject symbols. // // resolve() may trigger this->fetch() if an existing symbol is an // undefined symbol. If that happens, this LazyObjFile has served // its purpose, and we can exit from the loop early. - for (Symbol *Sym : this->Symbols) { - if (!Sym) + for (Symbol *sym : this->symbols) { + if (!sym) continue; - Sym->resolve(LazyObject{*this, Sym->getName()}); + sym->resolve(LazyObject{*this, sym->getName()}); // MemoryBuffer is emptied if this file is instantiated as ObjFile. - if (MB.getBuffer().empty()) + if (mb.getBuffer().empty()) return; } return; } } -std::string elf::replaceThinLTOSuffix(StringRef Path) { - StringRef Suffix = Config->ThinLTOObjectSuffixReplace.first; - StringRef Repl = Config->ThinLTOObjectSuffixReplace.second; - - if (Path.consume_back(Suffix)) - return (Path + Repl).str(); - return Path; +std::string elf::replaceThinLTOSuffix(StringRef path) { + StringRef suffix = config->thinLTOObjectSuffixReplace.first; + StringRef repl = config->thinLTOObjectSuffixReplace.second; + + if (path.consume_back(suffix)) + return (path + repl).str(); + return path; } template void BitcodeFile::parse(); Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -31,7 +31,7 @@ template class ObjFile; class OutputSection; -extern std::vector Partitions; +extern std::vector partitions; // This is the base class of all sections that lld handles. Some are sections in // input files, some are sections in the produced output file and some exist @@ -41,18 +41,18 @@ public: enum Kind { Regular, EHFrame, Merge, Synthetic, Output }; - Kind kind() const { return (Kind)SectionKind; } + Kind kind() const { return (Kind)sectionKind; } - StringRef Name; + StringRef name; // This pointer points to the "real" instance of this instance. // Usually Repl == this. However, if ICF merges two sections, // Repl pointer of one section points to another section. So, // if you need to get a pointer to this instance, do not use // this but instead this->Repl. - SectionBase *Repl; + SectionBase *repl; - unsigned SectionKind : 3; + unsigned sectionKind : 3; // The next three bit fields are only used by InputSectionBase, but we // put them here so the struct packs better. @@ -68,26 +68,26 @@ // .foo takes all .text sections, and .bar becomes empty. To achieve // this, we need to memorize whether a section has been placed or // not for each input section. - unsigned Assigned : 1; + unsigned assigned : 1; - unsigned Bss : 1; + unsigned bss : 1; // Set for sections that should not be folded by ICF. - unsigned KeepUnique : 1; + unsigned keepUnique : 1; // The 1-indexed partition that this section is assigned to by the garbage // collector, or 0 if this section is dead. Normally there is only one // partition, so this will either be 0 or 1. - uint8_t Partition; + uint8_t partition; elf::Partition &getPartition() const; // These corresponds to the fields in Elf_Shdr. - uint32_t Alignment; - uint64_t Flags; - uint64_t Entsize; - uint32_t Type; - uint32_t Link; - uint32_t Info; + uint32_t alignment; + uint64_t flags; + uint64_t entsize; + uint32_t type; + uint32_t link; + uint32_t info; OutputSection *getOutputSection(); const OutputSection *getOutputSection() const { @@ -96,55 +96,55 @@ // Translate an offset in the input section to an offset in the output // section. - uint64_t getOffset(uint64_t Offset) const; + uint64_t getOffset(uint64_t offset) const; - uint64_t getVA(uint64_t Offset = 0) const; + uint64_t getVA(uint64_t offset = 0) const; - bool isLive() const { return Partition != 0; } - void markLive() { Partition = 1; } - void markDead() { Partition = 0; } + bool isLive() const { return partition != 0; } + void markLive() { partition = 1; } + void markDead() { partition = 0; } protected: - SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags, - uint64_t Entsize, uint64_t Alignment, uint32_t Type, - uint32_t Info, uint32_t Link) - : Name(Name), Repl(this), SectionKind(SectionKind), Assigned(false), - Bss(false), KeepUnique(false), Partition(0), Alignment(Alignment), - Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) {} + SectionBase(Kind sectionKind, StringRef name, uint64_t flags, + uint64_t entsize, uint64_t alignment, uint32_t type, + uint32_t info, uint32_t link) + : name(name), repl(this), sectionKind(sectionKind), assigned(false), + bss(false), keepUnique(false), partition(0), alignment(alignment), + flags(flags), entsize(entsize), type(type), link(link), info(info) {} }; // This corresponds to a section of an input file. class InputSectionBase : public SectionBase { public: template - InputSectionBase(ObjFile &File, const typename ELFT::Shdr &Header, - StringRef Name, Kind SectionKind); + InputSectionBase(ObjFile &file, const typename ELFT::Shdr &header, + StringRef name, Kind sectionKind); - InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type, - uint64_t Entsize, uint32_t Link, uint32_t Info, - uint32_t Alignment, ArrayRef Data, StringRef Name, - Kind SectionKind); + InputSectionBase(InputFile *file, uint64_t flags, uint32_t type, + uint64_t entsize, uint32_t link, uint32_t info, + uint32_t alignment, ArrayRef data, StringRef name, + Kind sectionKind); - static bool classof(const SectionBase *S) { return S->kind() != Output; } + static bool classof(const SectionBase *s) { return s->kind() != Output; } // Relocations that refer to this section. - unsigned NumRelocations : 31; - unsigned AreRelocsRela : 1; - const void *FirstRelocation = nullptr; + unsigned numRelocations : 31; + unsigned areRelocsRela : 1; + const void *firstRelocation = nullptr; // The file which contains this section. Its dynamic type is always // ObjFile, but in order to avoid ELFT, we use InputFile as // its static type. - InputFile *File; + InputFile *file; template ObjFile *getFile() const { - return cast_or_null>(File); + return cast_or_null>(file); } ArrayRef data() const { - if (UncompressedSize >= 0) + if (uncompressedSize >= 0) uncompress(); - return RawData; + return rawData; } uint64_t getOffsetInFile() const; @@ -153,24 +153,24 @@ // like .eh_frame and merge sections are first combined into a // synthetic section that is then added to an output section. In all // cases this points one level up. - SectionBase *Parent = nullptr; + SectionBase *parent = nullptr; template ArrayRef rels() const { - assert(!AreRelocsRela); + assert(!areRelocsRela); return llvm::makeArrayRef( - static_cast(FirstRelocation), - NumRelocations); + static_cast(firstRelocation), + numRelocations); } template ArrayRef relas() const { - assert(AreRelocsRela); + assert(areRelocsRela); return llvm::makeArrayRef( - static_cast(FirstRelocation), - NumRelocations); + static_cast(firstRelocation), + numRelocations); } // InputSections that are dependent on us (reverse dependency for GC) - llvm::TinyPtrVector DependentSections; + llvm::TinyPtrVector dependentSections; // Returns the size of this section (even if this is a common or BSS.) size_t getSize() const; @@ -180,23 +180,23 @@ // Get the function symbol that encloses this offset from within the // section. template - Defined *getEnclosingFunction(uint64_t Offset); + Defined *getEnclosingFunction(uint64_t offset); // Returns a source location string. Used to construct an error message. - template std::string getLocation(uint64_t Offset); - std::string getSrcMsg(const Symbol &Sym, uint64_t Offset); - std::string getObjMsg(uint64_t Offset); + template std::string getLocation(uint64_t offset); + std::string getSrcMsg(const Symbol &sym, uint64_t offset); + std::string getObjMsg(uint64_t offset); // Each section knows how to relocate itself. These functions apply // relocations, assuming that Buf points to this section's copy in // the mmap'ed output buffer. - template void relocate(uint8_t *Buf, uint8_t *BufEnd); - void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd); + template void relocate(uint8_t *buf, uint8_t *bufEnd); + void relocateAlloc(uint8_t *buf, uint8_t *bufEnd); // The native ELF reloc data type is not very convenient to handle. // So we convert ELF reloc records to our own records in Relocations.cpp. // This vector contains such "cooked" relocations. - std::vector Relocations; + std::vector relocations; // A function compiled with -fsplit-stack calling a function // compiled without -fsplit-stack needs its prologue adjusted. Find @@ -204,26 +204,26 @@ // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more // information. template - void adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End); + void adjustSplitStackFunctionPrologues(uint8_t *buf, uint8_t *end); template llvm::ArrayRef getDataAs() const { - size_t S = data().size(); - assert(S % sizeof(T) == 0); - return llvm::makeArrayRef((const T *)data().data(), S / sizeof(T)); + size_t s = data().size(); + assert(s % sizeof(T) == 0); + return llvm::makeArrayRef((const T *)data().data(), s / sizeof(T)); } protected: void parseCompressedHeader(); void uncompress() const; - mutable ArrayRef RawData; + mutable ArrayRef rawData; // This field stores the uncompressed size of the compressed data in RawData, // or -1 if RawData is not compressed (either because the section wasn't // compressed in the first place, or because we ended up uncompressing it). // Since the feature is not used often, this is usually -1. - mutable int64_t UncompressedSize = -1; + mutable int64_t uncompressedSize = -1; }; // SectionPiece represents a piece of splittable section contents. @@ -231,13 +231,13 @@ // have to be as compact as possible, which is why we don't store the size (can // be found by looking at the next one). struct SectionPiece { - SectionPiece(size_t Off, uint32_t Hash, bool Live) - : InputOff(Off), Live(Live || !Config->GcSections), Hash(Hash >> 1) {} + SectionPiece(size_t off, uint32_t hash, bool live) + : inputOff(off), live(live || !config->gcSections), hash(hash >> 1) {} - uint32_t InputOff; - uint32_t Live : 1; - uint32_t Hash : 31; - uint64_t OutputOff = 0; + uint32_t inputOff; + uint32_t live : 1; + uint32_t hash : 31; + uint64_t outputOff = 0; }; static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big"); @@ -246,74 +246,74 @@ class MergeInputSection : public InputSectionBase { public: template - MergeInputSection(ObjFile &F, const typename ELFT::Shdr &Header, - StringRef Name); - MergeInputSection(uint64_t Flags, uint32_t Type, uint64_t Entsize, - ArrayRef Data, StringRef Name); + MergeInputSection(ObjFile &f, const typename ELFT::Shdr &header, + StringRef name); + MergeInputSection(uint64_t flags, uint32_t type, uint64_t entsize, + ArrayRef data, StringRef name); - static bool classof(const SectionBase *S) { return S->kind() == Merge; } + static bool classof(const SectionBase *s) { return s->kind() == Merge; } void splitIntoPieces(); // Translate an offset in the input section to an offset in the parent // MergeSyntheticSection. - uint64_t getParentOffset(uint64_t Offset) const; + uint64_t getParentOffset(uint64_t offset) const; // Splittable sections are handled as a sequence of data // rather than a single large blob of data. - std::vector Pieces; + std::vector pieces; // Returns I'th piece's data. This function is very hot when // string merging is enabled, so we want to inline. LLVM_ATTRIBUTE_ALWAYS_INLINE - llvm::CachedHashStringRef getData(size_t I) const { - size_t Begin = Pieces[I].InputOff; - size_t End = - (Pieces.size() - 1 == I) ? data().size() : Pieces[I + 1].InputOff; - return {toStringRef(data().slice(Begin, End - Begin)), Pieces[I].Hash}; + llvm::CachedHashStringRef getData(size_t i) const { + size_t begin = pieces[i].inputOff; + size_t end = + (pieces.size() - 1 == i) ? data().size() : pieces[i + 1].inputOff; + return {toStringRef(data().slice(begin, end - begin)), pieces[i].hash}; } // Returns the SectionPiece at a given input section offset. - SectionPiece *getSectionPiece(uint64_t Offset); - const SectionPiece *getSectionPiece(uint64_t Offset) const { - return const_cast(this)->getSectionPiece(Offset); + SectionPiece *getSectionPiece(uint64_t offset); + const SectionPiece *getSectionPiece(uint64_t offset) const { + return const_cast(this)->getSectionPiece(offset); } SyntheticSection *getParent() const; private: - void splitStrings(ArrayRef A, size_t Size); - void splitNonStrings(ArrayRef A, size_t Size); + void splitStrings(ArrayRef a, size_t size); + void splitNonStrings(ArrayRef a, size_t size); }; struct EhSectionPiece { - EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size, - unsigned FirstRelocation) - : InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {} + EhSectionPiece(size_t off, InputSectionBase *sec, uint32_t size, + unsigned firstRelocation) + : inputOff(off), sec(sec), size(size), firstRelocation(firstRelocation) {} ArrayRef data() { - return {Sec->data().data() + this->InputOff, Size}; + return {sec->data().data() + this->inputOff, size}; } - size_t InputOff; - ssize_t OutputOff = -1; - InputSectionBase *Sec; - uint32_t Size; - unsigned FirstRelocation; + size_t inputOff; + ssize_t outputOff = -1; + InputSectionBase *sec; + uint32_t size; + unsigned firstRelocation; }; // This corresponds to a .eh_frame section of an input file. class EhInputSection : public InputSectionBase { public: template - EhInputSection(ObjFile &F, const typename ELFT::Shdr &Header, - StringRef Name); - static bool classof(const SectionBase *S) { return S->kind() == EHFrame; } + EhInputSection(ObjFile &f, const typename ELFT::Shdr &header, + StringRef name); + static bool classof(const SectionBase *s) { return s->kind() == EHFrame; } template void split(); - template void split(ArrayRef Rels); + template void split(ArrayRef rels); // Splittable sections are handled as a sequence of data // rather than a single large blob of data. - std::vector Pieces; + std::vector pieces; SyntheticSection *getParent() const; }; @@ -324,17 +324,17 @@ // .eh_frame. It also includes the synthetic sections themselves. class InputSection : public InputSectionBase { public: - InputSection(InputFile *F, uint64_t Flags, uint32_t Type, uint32_t Alignment, - ArrayRef Data, StringRef Name, Kind K = Regular); + InputSection(InputFile *f, uint64_t flags, uint32_t type, uint32_t alignment, + ArrayRef data, StringRef name, Kind k = Regular); template - InputSection(ObjFile &F, const typename ELFT::Shdr &Header, - StringRef Name); + InputSection(ObjFile &f, const typename ELFT::Shdr &header, + StringRef name); // Write this section to a mmap'ed file, assuming Buf is pointing to // beginning of the output section. - template void writeTo(uint8_t *Buf); + template void writeTo(uint8_t *buf); - uint64_t getOffset(uint64_t Offset) const { return OutSecOff + Offset; } + uint64_t getOffset(uint64_t offset) const { return outSecOff + offset; } OutputSection *getParent() const; @@ -342,32 +342,32 @@ // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER // sections. After assignAddresses is called, it represents the offset from // the beginning of the output section this section was assigned to. - uint64_t OutSecOff = 0; + uint64_t outSecOff = 0; - static bool classof(const SectionBase *S); + static bool classof(const SectionBase *s); InputSectionBase *getRelocatedSection() const; template - void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); + void relocateNonAlloc(uint8_t *buf, llvm::ArrayRef rels); // Used by ICF. - uint32_t Class[2] = {0, 0}; + uint32_t eqClass[2] = {0, 0}; // Called by ICF to merge two input sections. - void replace(InputSection *Other); + void replace(InputSection *other); - static InputSection Discarded; + static InputSection discarded; private: template - void copyRelocations(uint8_t *Buf, llvm::ArrayRef Rels); + void copyRelocations(uint8_t *buf, llvm::ArrayRef rels); - template void copyShtGroup(uint8_t *Buf); + template void copyShtGroup(uint8_t *buf); }; // The list of all input sections. -extern std::vector InputSections; +extern std::vector inputSections; } // namespace elf Index: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -40,52 +40,52 @@ using namespace lld; using namespace lld::elf; -std::vector elf::InputSections; +std::vector elf::inputSections; // Returns a string to construct an error message. -std::string lld::toString(const InputSectionBase *Sec) { - return (toString(Sec->File) + ":(" + Sec->Name + ")").str(); +std::string lld::toString(const InputSectionBase *sec) { + return (toString(sec->file) + ":(" + sec->name + ")").str(); } template -static ArrayRef getSectionContents(ObjFile &File, - const typename ELFT::Shdr &Hdr) { - if (Hdr.sh_type == SHT_NOBITS) - return makeArrayRef(nullptr, Hdr.sh_size); - return check(File.getObj().getSectionContents(&Hdr)); +static ArrayRef getSectionContents(ObjFile &file, + const typename ELFT::Shdr &hdr) { + if (hdr.sh_type == SHT_NOBITS) + return makeArrayRef(nullptr, hdr.sh_size); + return check(file.getObj().getSectionContents(&hdr)); } -InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, - uint32_t Type, uint64_t Entsize, - uint32_t Link, uint32_t Info, - uint32_t Alignment, ArrayRef Data, - StringRef Name, Kind SectionKind) - : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, - Link), - File(File), RawData(Data) { +InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags, + uint32_t type, uint64_t entsize, + uint32_t link, uint32_t info, + uint32_t alignment, ArrayRef data, + StringRef name, Kind sectionKind) + : SectionBase(sectionKind, name, flags, entsize, alignment, type, info, + link), + file(file), rawData(data) { // In order to reduce memory allocation, we assume that mergeable // sections are smaller than 4 GiB, which is not an unreasonable // assumption as of 2017. - if (SectionKind == SectionBase::Merge && RawData.size() > UINT32_MAX) + if (sectionKind == SectionBase::Merge && rawData.size() > UINT32_MAX) error(toString(this) + ": section too large"); - NumRelocations = 0; - AreRelocsRela = false; + numRelocations = 0; + areRelocsRela = false; // The ELF spec states that a value of 0 means the section has // no alignment constraits. - uint32_t V = std::max(Alignment, 1); - if (!isPowerOf2_64(V)) + uint32_t v = std::max(alignment, 1); + if (!isPowerOf2_64(v)) fatal(toString(this) + ": sh_addralign is not a power of 2"); - this->Alignment = V; + this->alignment = v; // In ELF, each section can be compressed by zlib, and if compressed, // section name may be mangled by appending "z" (e.g. ".zdebug_info"). // If that's the case, demangle section name so that we can handle a // section as if it weren't compressed. - if ((Flags & SHF_COMPRESSED) || Name.startswith(".zdebug")) { + if ((flags & SHF_COMPRESSED) || name.startswith(".zdebug")) { if (!zlib::isAvailable()) - error(toString(File) + ": contains a compressed section, " + + error(toString(file) + ": contains a compressed section, " + "but zlib is not available"); parseCompressedHeader(); } @@ -94,11 +94,11 @@ // Drop SHF_GROUP bit unless we are producing a re-linkable object file. // SHF_GROUP is a marker that a section belongs to some comdat group. // That flag doesn't make sense in an executable. -static uint64_t getFlags(uint64_t Flags) { - Flags &= ~(uint64_t)SHF_INFO_LINK; - if (!Config->Relocatable) - Flags &= ~(uint64_t)SHF_GROUP; - return Flags; +static uint64_t getFlags(uint64_t flags) { + flags &= ~(uint64_t)SHF_INFO_LINK; + if (!config->relocatable) + flags &= ~(uint64_t)SHF_GROUP; + return flags; } // GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of @@ -111,99 +111,99 @@ // // This function forces SHT_{INIT,FINI}_ARRAY so that we can handle // incorrect inputs as if they were correct from the beginning. -static uint64_t getType(uint64_t Type, StringRef Name) { - if (Type == SHT_PROGBITS && Name.startswith(".init_array.")) +static uint64_t getType(uint64_t type, StringRef name) { + if (type == SHT_PROGBITS && name.startswith(".init_array.")) return SHT_INIT_ARRAY; - if (Type == SHT_PROGBITS && Name.startswith(".fini_array.")) + if (type == SHT_PROGBITS && name.startswith(".fini_array.")) return SHT_FINI_ARRAY; - return Type; + return type; } template -InputSectionBase::InputSectionBase(ObjFile &File, - const typename ELFT::Shdr &Hdr, - StringRef Name, Kind SectionKind) - : InputSectionBase(&File, getFlags(Hdr.sh_flags), - getType(Hdr.sh_type, Name), Hdr.sh_entsize, Hdr.sh_link, - Hdr.sh_info, Hdr.sh_addralign, - getSectionContents(File, Hdr), Name, SectionKind) { +InputSectionBase::InputSectionBase(ObjFile &file, + const typename ELFT::Shdr &hdr, + StringRef name, Kind sectionKind) + : InputSectionBase(&file, getFlags(hdr.sh_flags), + getType(hdr.sh_type, name), hdr.sh_entsize, hdr.sh_link, + hdr.sh_info, hdr.sh_addralign, + getSectionContents(file, hdr), name, sectionKind) { // We reject object files having insanely large alignments even though // they are allowed by the spec. I think 4GB is a reasonable limitation. // We might want to relax this in the future. - if (Hdr.sh_addralign > UINT32_MAX) - fatal(toString(&File) + ": section sh_addralign is too large"); + if (hdr.sh_addralign > UINT32_MAX) + fatal(toString(&file) + ": section sh_addralign is too large"); } size_t InputSectionBase::getSize() const { - if (auto *S = dyn_cast(this)) - return S->getSize(); - if (UncompressedSize >= 0) - return UncompressedSize; - return RawData.size(); + if (auto *s = dyn_cast(this)) + return s->getSize(); + if (uncompressedSize >= 0) + return uncompressedSize; + return rawData.size(); } void InputSectionBase::uncompress() const { - size_t Size = UncompressedSize; - char *UncompressedBuf; + size_t size = uncompressedSize; + char *uncompressedBuf; { - static std::mutex Mu; - std::lock_guard Lock(Mu); - UncompressedBuf = BAlloc.Allocate(Size); + static std::mutex mu; + std::lock_guard lock(mu); + uncompressedBuf = BAlloc.Allocate(size); } - if (Error E = zlib::uncompress(toStringRef(RawData), UncompressedBuf, Size)) + if (Error e = zlib::uncompress(toStringRef(rawData), uncompressedBuf, size)) fatal(toString(this) + - ": uncompress failed: " + llvm::toString(std::move(E))); - RawData = makeArrayRef((uint8_t *)UncompressedBuf, Size); - UncompressedSize = -1; + ": uncompress failed: " + llvm::toString(std::move(e))); + rawData = makeArrayRef((uint8_t *)uncompressedBuf, size); + uncompressedSize = -1; } uint64_t InputSectionBase::getOffsetInFile() const { - const uint8_t *FileStart = (const uint8_t *)File->MB.getBufferStart(); - const uint8_t *SecStart = data().begin(); - return SecStart - FileStart; + const uint8_t *fileStart = (const uint8_t *)file->mb.getBufferStart(); + const uint8_t *secStart = data().begin(); + return secStart - fileStart; } -uint64_t SectionBase::getOffset(uint64_t Offset) const { +uint64_t SectionBase::getOffset(uint64_t offset) const { switch (kind()) { case Output: { - auto *OS = cast(this); + auto *os = cast(this); // For output sections we treat offset -1 as the end of the section. - return Offset == uint64_t(-1) ? OS->Size : Offset; + return offset == uint64_t(-1) ? os->size : offset; } case Regular: case Synthetic: - return cast(this)->getOffset(Offset); + return cast(this)->getOffset(offset); case EHFrame: // The file crtbeginT.o has relocations pointing to the start of an empty // .eh_frame that is known to be the first in the link. It does that to // identify the start of the output .eh_frame. - return Offset; + return offset; case Merge: - const MergeInputSection *MS = cast(this); - if (InputSection *IS = MS->getParent()) - return IS->getOffset(MS->getParentOffset(Offset)); - return MS->getParentOffset(Offset); + const MergeInputSection *ms = cast(this); + if (InputSection *isec = ms->getParent()) + return isec->getOffset(ms->getParentOffset(offset)); + return ms->getParentOffset(offset); } llvm_unreachable("invalid section kind"); } -uint64_t SectionBase::getVA(uint64_t Offset) const { - const OutputSection *Out = getOutputSection(); - return (Out ? Out->Addr : 0) + getOffset(Offset); +uint64_t SectionBase::getVA(uint64_t offset) const { + const OutputSection *out = getOutputSection(); + return (out ? out->addr : 0) + getOffset(offset); } OutputSection *SectionBase::getOutputSection() { - InputSection *Sec; - if (auto *IS = dyn_cast(this)) - Sec = IS; - else if (auto *MS = dyn_cast(this)) - Sec = MS->getParent(); - else if (auto *EH = dyn_cast(this)) - Sec = EH->getParent(); + InputSection *sec; + if (auto *isec = dyn_cast(this)) + sec = isec; + else if (auto *ms = dyn_cast(this)) + sec = ms->getParent(); + else if (auto *eh = dyn_cast(this)) + sec = eh->getParent(); else return cast(this); - return Sec ? Sec->getParent() : nullptr; + return sec ? sec->getParent() : nullptr; } // When a section is compressed, `RawData` consists with a header followed @@ -214,109 +214,109 @@ using Chdr32 = typename ELF32LE::Chdr; // Old-style header - if (Name.startswith(".zdebug")) { - if (!toStringRef(RawData).startswith("ZLIB")) { + if (name.startswith(".zdebug")) { + if (!toStringRef(rawData).startswith("ZLIB")) { error(toString(this) + ": corrupted compressed section header"); return; } - RawData = RawData.slice(4); + rawData = rawData.slice(4); - if (RawData.size() < 8) { + if (rawData.size() < 8) { error(toString(this) + ": corrupted compressed section header"); return; } - UncompressedSize = read64be(RawData.data()); - RawData = RawData.slice(8); + uncompressedSize = read64be(rawData.data()); + rawData = rawData.slice(8); // Restore the original section name. // (e.g. ".zdebug_info" -> ".debug_info") - Name = Saver.save("." + Name.substr(2)); + name = Saver.save("." + name.substr(2)); return; } - assert(Flags & SHF_COMPRESSED); - Flags &= ~(uint64_t)SHF_COMPRESSED; + assert(flags & SHF_COMPRESSED); + flags &= ~(uint64_t)SHF_COMPRESSED; // New-style 64-bit header - if (Config->Is64) { - if (RawData.size() < sizeof(Chdr64)) { + if (config->is64) { + if (rawData.size() < sizeof(Chdr64)) { error(toString(this) + ": corrupted compressed section"); return; } - auto *Hdr = reinterpret_cast(RawData.data()); - if (Hdr->ch_type != ELFCOMPRESS_ZLIB) { + auto *hdr = reinterpret_cast(rawData.data()); + if (hdr->ch_type != ELFCOMPRESS_ZLIB) { error(toString(this) + ": unsupported compression type"); return; } - UncompressedSize = Hdr->ch_size; - Alignment = std::max(Hdr->ch_addralign, 1); - RawData = RawData.slice(sizeof(*Hdr)); + uncompressedSize = hdr->ch_size; + alignment = std::max(hdr->ch_addralign, 1); + rawData = rawData.slice(sizeof(*hdr)); return; } // New-style 32-bit header - if (RawData.size() < sizeof(Chdr32)) { + if (rawData.size() < sizeof(Chdr32)) { error(toString(this) + ": corrupted compressed section"); return; } - auto *Hdr = reinterpret_cast(RawData.data()); - if (Hdr->ch_type != ELFCOMPRESS_ZLIB) { + auto *hdr = reinterpret_cast(rawData.data()); + if (hdr->ch_type != ELFCOMPRESS_ZLIB) { error(toString(this) + ": unsupported compression type"); return; } - UncompressedSize = Hdr->ch_size; - Alignment = std::max(Hdr->ch_addralign, 1); - RawData = RawData.slice(sizeof(*Hdr)); + uncompressedSize = hdr->ch_size; + alignment = std::max(hdr->ch_addralign, 1); + rawData = rawData.slice(sizeof(*hdr)); } InputSection *InputSectionBase::getLinkOrderDep() const { - assert(Link); - assert(Flags & SHF_LINK_ORDER); - return cast(File->getSections()[Link]); + assert(link); + assert(flags & SHF_LINK_ORDER); + return cast(file->getSections()[link]); } // Find a function symbol that encloses a given location. template -Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) { - for (Symbol *B : File->getSymbols()) - if (Defined *D = dyn_cast(B)) - if (D->Section == this && D->Type == STT_FUNC && D->Value <= Offset && - Offset < D->Value + D->Size) - return D; +Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) { + for (Symbol *b : file->getSymbols()) + if (Defined *d = dyn_cast(b)) + if (d->section == this && d->type == STT_FUNC && d->value <= offset && + offset < d->value + d->size) + return d; return nullptr; } // Returns a source location string. Used to construct an error message. template -std::string InputSectionBase::getLocation(uint64_t Offset) { - std::string SecAndOffset = (Name + "+0x" + utohexstr(Offset)).str(); +std::string InputSectionBase::getLocation(uint64_t offset) { + std::string secAndOffset = (name + "+0x" + utohexstr(offset)).str(); // We don't have file for synthetic sections. if (getFile() == nullptr) - return (Config->OutputFile + ":(" + SecAndOffset + ")") + return (config->outputFile + ":(" + secAndOffset + ")") .str(); // First check if we can get desired values from debugging information. - if (Optional Info = getFile()->getDILineInfo(this, Offset)) - return Info->FileName + ":" + std::to_string(Info->Line) + ":(" + - SecAndOffset + ")"; + if (Optional info = getFile()->getDILineInfo(this, offset)) + return info->FileName + ":" + std::to_string(info->Line) + ":(" + + secAndOffset + ")"; // File->SourceFile contains STT_FILE symbol that contains a // source file name. If it's missing, we use an object file name. - std::string SrcFile = getFile()->SourceFile; - if (SrcFile.empty()) - SrcFile = toString(File); + std::string srcFile = getFile()->sourceFile; + if (srcFile.empty()) + srcFile = toString(file); - if (Defined *D = getEnclosingFunction(Offset)) - return SrcFile + ":(function " + toString(*D) + ": " + SecAndOffset + ")"; + if (Defined *d = getEnclosingFunction(offset)) + return srcFile + ":(function " + toString(*d) + ": " + secAndOffset + ")"; // If there's no symbol, print out the offset in the section. - return (SrcFile + ":(" + SecAndOffset + ")"); + return (srcFile + ":(" + secAndOffset + ")"); } // This function is intended to be used for constructing an error message. @@ -325,8 +325,8 @@ // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) // // Returns an empty string if there's no way to get line info. -std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) { - return File->getSrcMsg(Sym, *this, Offset); +std::string InputSectionBase::getSrcMsg(const Symbol &sym, uint64_t offset) { + return file->getSrcMsg(sym, *this, offset); } // Returns a filename string along with an optional section name. This @@ -338,96 +338,96 @@ // or // // path/to/foo.o:(function bar) in archive path/to/bar.a -std::string InputSectionBase::getObjMsg(uint64_t Off) { - std::string Filename = File->getName(); +std::string InputSectionBase::getObjMsg(uint64_t off) { + std::string filename = file->getName(); - std::string Archive; - if (!File->ArchiveName.empty()) - Archive = " in archive " + File->ArchiveName; + std::string archive; + if (!file->archiveName.empty()) + archive = " in archive " + file->archiveName; // Find a symbol that encloses a given location. - for (Symbol *B : File->getSymbols()) - if (auto *D = dyn_cast(B)) - if (D->Section == this && D->Value <= Off && Off < D->Value + D->Size) - return Filename + ":(" + toString(*D) + ")" + Archive; + for (Symbol *b : file->getSymbols()) + if (auto *d = dyn_cast(b)) + if (d->section == this && d->value <= off && off < d->value + d->size) + return filename + ":(" + toString(*d) + ")" + archive; // If there's no symbol, print out the offset in the section. - return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive) + return (filename + ":(" + name + "+0x" + utohexstr(off) + ")" + archive) .str(); } -InputSection InputSection::Discarded(nullptr, 0, 0, 0, ArrayRef(), ""); +InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef(), ""); -InputSection::InputSection(InputFile *F, uint64_t Flags, uint32_t Type, - uint32_t Alignment, ArrayRef Data, - StringRef Name, Kind K) - : InputSectionBase(F, Flags, Type, - /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data, - Name, K) {} +InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type, + uint32_t alignment, ArrayRef data, + StringRef name, Kind k) + : InputSectionBase(f, flags, type, + /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, alignment, data, + name, k) {} template -InputSection::InputSection(ObjFile &F, const typename ELFT::Shdr &Header, - StringRef Name) - : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {} - -bool InputSection::classof(const SectionBase *S) { - return S->kind() == SectionBase::Regular || - S->kind() == SectionBase::Synthetic; +InputSection::InputSection(ObjFile &f, const typename ELFT::Shdr &header, + StringRef name) + : InputSectionBase(f, header, name, InputSectionBase::Regular) {} + +bool InputSection::classof(const SectionBase *s) { + return s->kind() == SectionBase::Regular || + s->kind() == SectionBase::Synthetic; } OutputSection *InputSection::getParent() const { - return cast_or_null(Parent); + return cast_or_null(parent); } // Copy SHT_GROUP section contents. Used only for the -r option. -template void InputSection::copyShtGroup(uint8_t *Buf) { +template void InputSection::copyShtGroup(uint8_t *buf) { // ELFT::Word is the 32-bit integral type in the target endianness. using u32 = typename ELFT::Word; - ArrayRef From = getDataAs(); - auto *To = reinterpret_cast(Buf); + ArrayRef from = getDataAs(); + auto *to = reinterpret_cast(buf); // The first entry is not a section number but a flag. - *To++ = From[0]; + *to++ = from[0]; // Adjust section numbers because section numbers in an input object // files are different in the output. - ArrayRef Sections = File->getSections(); - for (uint32_t Idx : From.slice(1)) - *To++ = Sections[Idx]->getOutputSection()->SectionIndex; + ArrayRef sections = file->getSections(); + for (uint32_t idx : from.slice(1)) + *to++ = sections[idx]->getOutputSection()->sectionIndex; } InputSectionBase *InputSection::getRelocatedSection() const { - if (!File || (Type != SHT_RELA && Type != SHT_REL)) + if (!file || (type != SHT_RELA && type != SHT_REL)) return nullptr; - ArrayRef Sections = File->getSections(); - return Sections[Info]; + ArrayRef sections = file->getSections(); + return sections[info]; } // This is used for -r and --emit-relocs. We can't use memcpy to copy // relocations because we need to update symbol table offset and section index // for each relocation. So we copy relocations one by one. template -void InputSection::copyRelocations(uint8_t *Buf, ArrayRef Rels) { - InputSectionBase *Sec = getRelocatedSection(); +void InputSection::copyRelocations(uint8_t *buf, ArrayRef rels) { + InputSectionBase *sec = getRelocatedSection(); - for (const RelTy &Rel : Rels) { - RelType Type = Rel.getType(Config->IsMips64EL); - const ObjFile *File = getFile(); - Symbol &Sym = File->getRelocTargetSym(Rel); + for (const RelTy &rel : rels) { + RelType type = rel.getType(config->isMips64EL); + const ObjFile *file = getFile(); + Symbol &sym = file->getRelocTargetSym(rel); - auto *P = reinterpret_cast(Buf); - Buf += sizeof(RelTy); + auto *p = reinterpret_cast(buf); + buf += sizeof(RelTy); if (RelTy::IsRela) - P->r_addend = getAddend(Rel); + p->r_addend = getAddend(rel); // Output section VA is zero for -r, so r_offset is an offset within the // section, but for --emit-relocs it is an virtual address. - P->r_offset = Sec->getVA(Rel.r_offset); - P->setSymbolAndType(In.SymTab->getSymbolIndex(&Sym), Type, - Config->IsMips64EL); + p->r_offset = sec->getVA(rel.r_offset); + p->setSymbolAndType(in.symTab->getSymbolIndex(&sym), type, + config->isMips64EL); - if (Sym.Type == STT_SECTION) { + if (sym.type == STT_SECTION) { // We combine multiple section symbols into only one per // section. This means we have to update the addend. That is // trivial for Elf_Rela, but for Elf_Rel we have to write to the @@ -440,34 +440,34 @@ // on .gcc_except_table and debug sections. // // See the comment in maybeReportUndefined for PPC64 .toc . - auto *D = dyn_cast(&Sym); - if (!D) { - if (!Sec->Name.startswith(".debug") && - !Sec->Name.startswith(".zdebug") && Sec->Name != ".eh_frame" && - Sec->Name != ".gcc_except_table" && Sec->Name != ".toc") { - uint32_t SecIdx = cast(Sym).DiscardedSecIdx; - Elf_Shdr_Impl Sec = - CHECK(File->getObj().sections(), File)[SecIdx]; + auto *d = dyn_cast(&sym); + if (!d) { + if (!sec->name.startswith(".debug") && + !sec->name.startswith(".zdebug") && sec->name != ".eh_frame" && + sec->name != ".gcc_except_table" && sec->name != ".toc") { + uint32_t secIdx = cast(sym).discardedSecIdx; + Elf_Shdr_Impl sec = + CHECK(file->getObj().sections(), file)[secIdx]; warn("relocation refers to a discarded section: " + - CHECK(File->getObj().getSectionName(&Sec), File) + - "\n>>> referenced by " + getObjMsg(P->r_offset)); + CHECK(file->getObj().getSectionName(&sec), file) + + "\n>>> referenced by " + getObjMsg(p->r_offset)); } - P->setSymbolAndType(0, 0, false); + p->setSymbolAndType(0, 0, false); continue; } - SectionBase *Section = D->Section->Repl; - if (!Section->isLive()) { - P->setSymbolAndType(0, 0, false); + SectionBase *section = d->section->repl; + if (!section->isLive()) { + p->setSymbolAndType(0, 0, false); continue; } - int64_t Addend = getAddend(Rel); - const uint8_t *BufLoc = Sec->data().begin() + Rel.r_offset; + int64_t addend = getAddend(rel); + const uint8_t *bufLoc = sec->data().begin() + rel.r_offset; if (!RelTy::IsRela) - Addend = Target->getImplicitAddend(BufLoc, Type); + addend = target->getImplicitAddend(bufLoc, type); - if (Config->EMachine == EM_MIPS && Config->Relocatable && - Target->getRelExpr(Type, Sym, BufLoc) == R_MIPS_GOTREL) { + if (config->emachine == EM_MIPS && config->relocatable && + target->getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) { // Some MIPS relocations depend on "gp" value. By default, // this value has 0x7ff0 offset from a .got section. But // relocatable files produced by a complier or a linker @@ -479,13 +479,13 @@ // individual "gp" values used by each input object file. // As a workaround we add the "gp" value to the relocation // addend and save it back to the file. - Addend += Sec->getFile()->MipsGp0; + addend += sec->getFile()->mipsGp0; } if (RelTy::IsRela) - P->r_addend = Sym.getVA(Addend) - Section->getOutputSection()->Addr; - else if (Config->Relocatable && Type != Target->NoneRel) - Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Addend, &Sym}); + p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; + else if (config->relocatable && type != target->noneRel) + sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym}); } } } @@ -495,13 +495,13 @@ // this context is the address of the place P. A further special case is that // branch relocations to an undefined weak reference resolve to the next // instruction. -static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A, - uint32_t P) { - switch (Type) { +static uint32_t getARMUndefinedRelativeWeakVA(RelType type, uint32_t a, + uint32_t p) { + switch (type) { // Unresolved branch relocations to weak references resolve to next // instruction, this will be either 2 or 4 bytes on from P. case R_ARM_THM_JUMP11: - return P + 2 + A; + return p + 2 + a; case R_ARM_CALL: case R_ARM_JUMP24: case R_ARM_PC24: @@ -509,10 +509,10 @@ case R_ARM_PREL31: case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: - return P + 4 + A; + return p + 4 + a; case R_ARM_THM_CALL: // We don't want an interworking BLX to ARM - return P + 5 + A; + return p + 5 + a; // Unresolved non branch pc-relative relocations // R_ARM_TARGET2 which can be resolved relatively is not present as it never // targets a weak-reference. @@ -521,29 +521,29 @@ case R_ARM_REL32: case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: - return P + A; + return p + a; } llvm_unreachable("ARM pc-relative relocation expected\n"); } // The comment above getARMUndefinedRelativeWeakVA applies to this function. -static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A, - uint64_t P) { - switch (Type) { +static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a, + uint64_t p) { + switch (type) { // Unresolved branch relocations to weak references resolve to next // instruction, this is 4 bytes on from P. case R_AARCH64_CALL26: case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: - return P + 4 + A; + return p + 4 + a; // Unresolved non branch pc-relative relocations case R_AARCH64_PREL16: case R_AARCH64_PREL32: case R_AARCH64_PREL64: case R_AARCH64_ADR_PREL_LO21: case R_AARCH64_LD_PREL_LO19: - return P + A; + return p + a; } llvm_unreachable("AArch64 pc-relative relocation expected\n"); } @@ -555,11 +555,11 @@ // The procedure call standard only defines a Read Write Position Independent // RWPI variant so in practice we should expect the static base to be the base // of the RW segment. -static uint64_t getARMStaticBase(const Symbol &Sym) { - OutputSection *OS = Sym.getOutputSection(); - if (!OS || !OS->PtLoad || !OS->PtLoad->FirstSec) - fatal("SBREL relocation to " + Sym.getName() + " without static base"); - return OS->PtLoad->FirstSec->Addr; +static uint64_t getARMStaticBase(const Symbol &sym) { + OutputSection *os = sym.getOutputSection(); + if (!os || !os->ptLoad || !os->ptLoad->firstSec) + fatal("SBREL relocation to " + sym.getName() + " without static base"); + return os->ptLoad->firstSec->addr; } // For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually @@ -568,115 +568,115 @@ // // This function returns the R_RISCV_PCREL_HI20 relocation from // R_RISCV_PCREL_LO12's symbol and addend. -static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) { - const Defined *D = cast(Sym); - if (!D->Section) { +static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) { + const Defined *d = cast(sym); + if (!d->section) { error("R_RISCV_PCREL_LO12 relocation points to an absolute symbol: " + - Sym->getName()); + sym->getName()); return nullptr; } - InputSection *IS = cast(D->Section); + InputSection *isec = cast(d->section); - if (Addend != 0) + if (addend != 0) warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " + - IS->getObjMsg(D->Value) + " is ignored"); + isec->getObjMsg(d->value) + " is ignored"); // Relocations are sorted by offset, so we can use std::equal_range to do // binary search. - Relocation R; - R.Offset = D->Value; - auto Range = - std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), R, - [](const Relocation &LHS, const Relocation &RHS) { - return LHS.Offset < RHS.Offset; + Relocation r; + r.offset = d->value; + auto range = + std::equal_range(isec->relocations.begin(), isec->relocations.end(), r, + [](const Relocation &lhs, const Relocation &rhs) { + return lhs.offset < rhs.offset; }); - for (auto It = Range.first; It != Range.second; ++It) - if (It->Type == R_RISCV_PCREL_HI20 || It->Type == R_RISCV_GOT_HI20 || - It->Type == R_RISCV_TLS_GD_HI20 || It->Type == R_RISCV_TLS_GOT_HI20) - return &*It; + for (auto it = range.first; it != range.second; ++it) + if (it->type == R_RISCV_PCREL_HI20 || it->type == R_RISCV_GOT_HI20 || + it->type == R_RISCV_TLS_GD_HI20 || it->type == R_RISCV_TLS_GOT_HI20) + return &*it; - error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + + error("R_RISCV_PCREL_LO12 relocation points to " + isec->getObjMsg(d->value) + " without an associated R_RISCV_PCREL_HI20 relocation"); return nullptr; } // A TLS symbol's virtual address is relative to the TLS segment. Add a // target-specific adjustment to produce a thread-pointer-relative offset. -static int64_t getTlsTpOffset(const Symbol &S) { +static int64_t getTlsTpOffset(const Symbol &s) { // On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0. - if (&S == ElfSym::TlsModuleBase) + if (&s == ElfSym::tlsModuleBase) return 0; - switch (Config->EMachine) { + switch (config->emachine) { case EM_ARM: case EM_AARCH64: // Variant 1. The thread pointer points to a TCB with a fixed 2-word size, // followed by a variable amount of alignment padding, followed by the TLS // segment. - return S.getVA(0) + alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align); + return s.getVA(0) + alignTo(config->wordsize * 2, Out::tlsPhdr->p_align); case EM_386: case EM_X86_64: // Variant 2. The TLS segment is located just before the thread pointer. - return S.getVA(0) - alignTo(Out::TlsPhdr->p_memsz, Out::TlsPhdr->p_align); + return s.getVA(0) - alignTo(Out::tlsPhdr->p_memsz, Out::tlsPhdr->p_align); case EM_PPC: case EM_PPC64: // The thread pointer points to a fixed offset from the start of the // executable's TLS segment. An offset of 0x7000 allows a signed 16-bit // offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the // program's TLS segment. - return S.getVA(0) - 0x7000; + return s.getVA(0) - 0x7000; case EM_RISCV: - return S.getVA(0); + return s.getVA(0); default: llvm_unreachable("unhandled Config->EMachine"); } } -static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, - uint64_t P, const Symbol &Sym, RelExpr Expr) { - switch (Expr) { +static uint64_t getRelocTargetVA(const InputFile *file, RelType type, int64_t a, + uint64_t p, const Symbol &sym, RelExpr expr) { + switch (expr) { case R_ABS: case R_DTPREL: case R_RELAX_TLS_LD_TO_LE_ABS: case R_RELAX_GOT_PC_NOPIC: case R_RISCV_ADD: - return Sym.getVA(A); + return sym.getVA(a); case R_ADDEND: - return A; + return a; case R_ARM_SBREL: - return Sym.getVA(A) - getARMStaticBase(Sym); + return sym.getVA(a) - getARMStaticBase(sym); case R_GOT: case R_RELAX_TLS_GD_TO_IE_ABS: - return Sym.getGotVA() + A; + return sym.getGotVA() + a; case R_GOTONLY_PC: - return In.Got->getVA() + A - P; + return in.got->getVA() + a - p; case R_GOTPLTONLY_PC: - return In.GotPlt->getVA() + A - P; + return in.gotPlt->getVA() + a - p; case R_GOTREL: case R_PPC64_RELAX_TOC: - return Sym.getVA(A) - In.Got->getVA(); + return sym.getVA(a) - in.got->getVA(); case R_GOTPLTREL: - return Sym.getVA(A) - In.GotPlt->getVA(); + return sym.getVA(a) - in.gotPlt->getVA(); case R_GOTPLT: case R_RELAX_TLS_GD_TO_IE_GOTPLT: - return Sym.getGotVA() + A - In.GotPlt->getVA(); + return sym.getGotVA() + a - in.gotPlt->getVA(); case R_TLSLD_GOT_OFF: case R_GOT_OFF: case R_RELAX_TLS_GD_TO_IE_GOT_OFF: - return Sym.getGotOffset() + A; + return sym.getGotOffset() + a; case R_AARCH64_GOT_PAGE_PC: case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: - return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); + return getAArch64Page(sym.getGotVA() + a) - getAArch64Page(p); case R_GOT_PC: case R_RELAX_TLS_GD_TO_IE: - return Sym.getGotVA() + A - P; + return sym.getGotVA() + a - p; case R_HEXAGON_GOT: - return Sym.getGotVA() - In.GotPlt->getVA(); + return sym.getGotVA() - in.gotPlt->getVA(); case R_MIPS_GOTREL: - return Sym.getVA(A) - In.MipsGot->getGp(File); + return sym.getVA(a) - in.mipsGot->getGp(file); case R_MIPS_GOT_GP: - return In.MipsGot->getGp(File) + A; + return in.mipsGot->getGp(file) + a; case R_MIPS_GOT_GP_PC: { // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target // is _gp_disp symbol. In that case we should use the following @@ -685,76 +685,76 @@ // microMIPS variants of these relocations use slightly different // expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi() // to correctly handle less-sugnificant bit of the microMIPS symbol. - uint64_t V = In.MipsGot->getGp(File) + A - P; - if (Type == R_MIPS_LO16 || Type == R_MICROMIPS_LO16) - V += 4; - if (Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_HI16) - V -= 1; - return V; + uint64_t v = in.mipsGot->getGp(file) + a - p; + if (type == R_MIPS_LO16 || type == R_MICROMIPS_LO16) + v += 4; + if (type == R_MICROMIPS_LO16 || type == R_MICROMIPS_HI16) + v -= 1; + return v; } case R_MIPS_GOT_LOCAL_PAGE: // If relocation against MIPS local symbol requires GOT entry, this entry // should be initialized by 'page address'. This address is high 16-bits // of sum the symbol's value and the addend. - return In.MipsGot->getVA() + In.MipsGot->getPageEntryOffset(File, Sym, A) - - In.MipsGot->getGp(File); + return in.mipsGot->getVA() + in.mipsGot->getPageEntryOffset(file, sym, a) - + in.mipsGot->getGp(file); case R_MIPS_GOT_OFF: case R_MIPS_GOT_OFF32: // In case of MIPS if a GOT relocation has non-zero addend this addend // should be applied to the GOT entry content not to the GOT entry offset. // That is why we use separate expression type. - return In.MipsGot->getVA() + In.MipsGot->getSymEntryOffset(File, Sym, A) - - In.MipsGot->getGp(File); + return in.mipsGot->getVA() + in.mipsGot->getSymEntryOffset(file, sym, a) - + in.mipsGot->getGp(file); case R_MIPS_TLSGD: - return In.MipsGot->getVA() + In.MipsGot->getGlobalDynOffset(File, Sym) - - In.MipsGot->getGp(File); + return in.mipsGot->getVA() + in.mipsGot->getGlobalDynOffset(file, sym) - + in.mipsGot->getGp(file); case R_MIPS_TLSLD: - return In.MipsGot->getVA() + In.MipsGot->getTlsIndexOffset(File) - - In.MipsGot->getGp(File); + return in.mipsGot->getVA() + in.mipsGot->getTlsIndexOffset(file) - + in.mipsGot->getGp(file); case R_AARCH64_PAGE_PC: { - uint64_t Val = Sym.isUndefWeak() ? P + A : Sym.getVA(A); - return getAArch64Page(Val) - getAArch64Page(P); + uint64_t val = sym.isUndefWeak() ? p + a : sym.getVA(a); + return getAArch64Page(val) - getAArch64Page(p); } case R_RISCV_PC_INDIRECT: { - if (const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A)) - return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), - *HiRel->Sym, HiRel->Expr); + if (const Relocation *hiRel = getRISCVPCRelHi20(&sym, a)) + return getRelocTargetVA(file, hiRel->type, hiRel->addend, sym.getVA(), + *hiRel->sym, hiRel->expr); return 0; } case R_PC: { - uint64_t Dest; - if (Sym.isUndefWeak()) { + uint64_t dest; + if (sym.isUndefWeak()) { // On ARM and AArch64 a branch to an undefined weak resolves to the // next instruction, otherwise the place. - if (Config->EMachine == EM_ARM) - Dest = getARMUndefinedRelativeWeakVA(Type, A, P); - else if (Config->EMachine == EM_AARCH64) - Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P); - else if (Config->EMachine == EM_PPC) - Dest = P; + if (config->emachine == EM_ARM) + dest = getARMUndefinedRelativeWeakVA(type, a, p); + else if (config->emachine == EM_AARCH64) + dest = getAArch64UndefinedRelativeWeakVA(type, a, p); + else if (config->emachine == EM_PPC) + dest = p; else - Dest = Sym.getVA(A); + dest = sym.getVA(a); } else { - Dest = Sym.getVA(A); + dest = sym.getVA(a); } - return Dest - P; + return dest - p; } case R_PLT: - return Sym.getPltVA() + A; + return sym.getPltVA() + a; case R_PLT_PC: case R_PPC64_CALL_PLT: - return Sym.getPltVA() + A - P; + return sym.getPltVA() + a - p; case R_PPC32_PLTREL: // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30 // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for // target VA compuation. - return Sym.getPltVA() - P; + return sym.getPltVA() - p; case R_PPC64_CALL: { - uint64_t SymVA = Sym.getVA(A); + uint64_t symVA = sym.getVA(a); // If we have an undefined weak symbol, we might get here with a symbol // address of zero. That could overflow, but the code must be unreachable, // so don't bother doing anything at all. - if (!SymVA) + if (!symVA) return 0; // PPC64 V2 ABI describes two entry points to a function. The global entry @@ -763,12 +763,12 @@ // the callee. For local calls the caller and callee share the same // TOC base and so the TOC pointer initialization code should be skipped by // branching to the local entry point. - return SymVA - P + getPPC64GlobalEntryToLocalEntryOffset(Sym.StOther); + return symVA - p + getPPC64GlobalEntryToLocalEntryOffset(sym.stOther); } case R_PPC64_TOCBASE: - return getPPC64TocBase() + A; + return getPPC64TocBase() + a; case R_RELAX_GOT_PC: - return Sym.getVA(A) - P; + return sym.getVA(a) - p; case R_RELAX_TLS_GD_TO_LE: case R_RELAX_TLS_IE_TO_LE: case R_RELAX_TLS_LD_TO_LE: @@ -777,35 +777,35 @@ // --noinhibit-exec, even a non-weak undefined reference may reach here. // Just return A, which matches R_ABS, and the behavior of some dynamic // loaders. - if (Sym.isUndefined()) - return A; - return getTlsTpOffset(Sym) + A; + if (sym.isUndefined()) + return a; + return getTlsTpOffset(sym) + a; case R_RELAX_TLS_GD_TO_LE_NEG: case R_NEG_TLS: - if (Sym.isUndefined()) - return A; - return -getTlsTpOffset(Sym) + A; + if (sym.isUndefined()) + return a; + return -getTlsTpOffset(sym) + a; case R_SIZE: - return Sym.getSize() + A; + return sym.getSize() + a; case R_TLSDESC: - return In.Got->getGlobalDynAddr(Sym) + A; + return in.got->getGlobalDynAddr(sym) + a; case R_TLSDESC_PC: - return In.Got->getGlobalDynAddr(Sym) + A - P; + return in.got->getGlobalDynAddr(sym) + a - p; case R_AARCH64_TLSDESC_PAGE: - return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - - getAArch64Page(P); + return getAArch64Page(in.got->getGlobalDynAddr(sym) + a) - + getAArch64Page(p); case R_TLSGD_GOT: - return In.Got->getGlobalDynOffset(Sym) + A; + return in.got->getGlobalDynOffset(sym) + a; case R_TLSGD_GOTPLT: - return In.Got->getVA() + In.Got->getGlobalDynOffset(Sym) + A - In.GotPlt->getVA(); + return in.got->getVA() + in.got->getGlobalDynOffset(sym) + a - in.gotPlt->getVA(); case R_TLSGD_PC: - return In.Got->getGlobalDynAddr(Sym) + A - P; + return in.got->getGlobalDynAddr(sym) + a - p; case R_TLSLD_GOTPLT: - return In.Got->getVA() + In.Got->getTlsIndexOff() + A - In.GotPlt->getVA(); + return in.got->getVA() + in.got->getTlsIndexOff() + a - in.gotPlt->getVA(); case R_TLSLD_GOT: - return In.Got->getTlsIndexOff() + A; + return in.got->getTlsIndexOff() + a; case R_TLSLD_PC: - return In.Got->getTlsIndexVA() + A - P; + return in.got->getTlsIndexVA() + a - p; default: llvm_unreachable("invalid expression"); } @@ -819,36 +819,36 @@ // So, we handle relocations for non-alloc sections directly in this // function as a performance optimization. template -void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef Rels) { - const unsigned Bits = sizeof(typename ELFT::uint) * 8; +void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { + const unsigned bits = sizeof(typename ELFT::uint) * 8; - for (const RelTy &Rel : Rels) { - RelType Type = Rel.getType(Config->IsMips64EL); + for (const RelTy &rel : rels) { + RelType type = rel.getType(config->isMips64EL); // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations // against _GLOBAL_OFFSET_TABLE_ for .debug_info. The bug has been fixed // in 2017 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630), but we // need to keep this bug-compatible code for a while. - if (Config->EMachine == EM_386 && Type == R_386_GOTPC) + if (config->emachine == EM_386 && type == R_386_GOTPC) continue; - uint64_t Offset = getOffset(Rel.r_offset); - uint8_t *BufLoc = Buf + Offset; - int64_t Addend = getAddend(Rel); + uint64_t offset = getOffset(rel.r_offset); + uint8_t *bufLoc = buf + offset; + int64_t addend = getAddend(rel); if (!RelTy::IsRela) - Addend += Target->getImplicitAddend(BufLoc, Type); + addend += target->getImplicitAddend(bufLoc, type); - Symbol &Sym = getFile()->getRelocTargetSym(Rel); - RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc); - if (Expr == R_NONE) + Symbol &sym = getFile()->getRelocTargetSym(rel); + RelExpr expr = target->getRelExpr(type, sym, bufLoc); + if (expr == R_NONE) continue; - if (Expr != R_ABS && Expr != R_DTPREL && Expr != R_RISCV_ADD) { - std::string Msg = getLocation(Offset) + - ": has non-ABS relocation " + toString(Type) + - " against symbol '" + toString(Sym) + "'"; - if (Expr != R_PC) { - error(Msg); + if (expr != R_ABS && expr != R_DTPREL && expr != R_RISCV_ADD) { + std::string msg = getLocation(offset) + + ": has non-ABS relocation " + toString(type) + + " against symbol '" + toString(sym) + "'"; + if (expr != R_PC) { + error(msg); return; } @@ -859,16 +859,16 @@ // relocations without any errors and relocate them as if they were at // address 0. For bug-compatibilty, we accept them with warnings. We // know Steel Bank Common Lisp as of 2018 have this bug. - warn(Msg); - Target->relocateOne(BufLoc, Type, - SignExtend64(Sym.getVA(Addend - Offset))); + warn(msg); + target->relocateOne(bufLoc, type, + SignExtend64(sym.getVA(addend - offset))); continue; } - if (Sym.isTls() && !Out::TlsPhdr) - Target->relocateOne(BufLoc, Type, 0); + if (sym.isTls() && !Out::tlsPhdr) + target->relocateOne(bufLoc, type, 0); else - Target->relocateOne(BufLoc, Type, SignExtend64(Sym.getVA(Addend))); + target->relocateOne(bufLoc, type, SignExtend64(sym.getVA(addend))); } } @@ -877,100 +877,100 @@ // relocations aimed to update addends. They are handled in relocateAlloc() // for allocatable sections, and this function does the same for // non-allocatable sections, such as sections with debug information. -static void relocateNonAllocForRelocatable(InputSection *Sec, uint8_t *Buf) { - const unsigned Bits = Config->Is64 ? 64 : 32; +static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) { + const unsigned bits = config->is64 ? 64 : 32; - for (const Relocation &Rel : Sec->Relocations) { + for (const Relocation &rel : sec->relocations) { // InputSection::copyRelocations() adds only R_ABS relocations. - assert(Rel.Expr == R_ABS); - uint8_t *BufLoc = Buf + Rel.Offset + Sec->OutSecOff; - uint64_t TargetVA = SignExtend64(Rel.Sym->getVA(Rel.Addend), Bits); - Target->relocateOne(BufLoc, Rel.Type, TargetVA); + assert(rel.expr == R_ABS); + uint8_t *bufLoc = buf + rel.offset + sec->outSecOff; + uint64_t targetVA = SignExtend64(rel.sym->getVA(rel.addend), bits); + target->relocateOne(bufLoc, rel.type, targetVA); } } template -void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) { - if (Flags & SHF_EXECINSTR) - adjustSplitStackFunctionPrologues(Buf, BufEnd); +void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { + if (flags & SHF_EXECINSTR) + adjustSplitStackFunctionPrologues(buf, bufEnd); - if (Flags & SHF_ALLOC) { - relocateAlloc(Buf, BufEnd); + if (flags & SHF_ALLOC) { + relocateAlloc(buf, bufEnd); return; } - auto *Sec = cast(this); - if (Config->Relocatable) - relocateNonAllocForRelocatable(Sec, Buf); - else if (Sec->AreRelocsRela) - Sec->relocateNonAlloc(Buf, Sec->template relas()); + auto *sec = cast(this); + if (config->relocatable) + relocateNonAllocForRelocatable(sec, buf); + else if (sec->areRelocsRela) + sec->relocateNonAlloc(buf, sec->template relas()); else - Sec->relocateNonAlloc(Buf, Sec->template rels()); + sec->relocateNonAlloc(buf, sec->template rels()); } -void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { - assert(Flags & SHF_ALLOC); - const unsigned Bits = Config->Wordsize * 8; - - for (const Relocation &Rel : Relocations) { - uint64_t Offset = Rel.Offset; - if (auto *Sec = dyn_cast(this)) - Offset += Sec->OutSecOff; - uint8_t *BufLoc = Buf + Offset; - RelType Type = Rel.Type; - - uint64_t AddrLoc = getOutputSection()->Addr + Offset; - RelExpr Expr = Rel.Expr; - uint64_t TargetVA = SignExtend64( - getRelocTargetVA(File, Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr), - Bits); +void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { + assert(flags & SHF_ALLOC); + const unsigned bits = config->wordsize * 8; + + for (const Relocation &rel : relocations) { + uint64_t offset = rel.offset; + if (auto *sec = dyn_cast(this)) + offset += sec->outSecOff; + uint8_t *bufLoc = buf + offset; + RelType type = rel.type; + + uint64_t addrLoc = getOutputSection()->addr + offset; + RelExpr expr = rel.expr; + uint64_t targetVA = SignExtend64( + getRelocTargetVA(file, type, rel.addend, addrLoc, *rel.sym, expr), + bits); - switch (Expr) { + switch (expr) { case R_RELAX_GOT_PC: case R_RELAX_GOT_PC_NOPIC: - Target->relaxGot(BufLoc, Type, TargetVA); + target->relaxGot(bufLoc, type, targetVA); break; case R_PPC64_RELAX_TOC: - if (!tryRelaxPPC64TocIndirection(Type, Rel, BufLoc)) - Target->relocateOne(BufLoc, Type, TargetVA); + if (!tryRelaxPPC64TocIndirection(type, rel, bufLoc)) + target->relocateOne(bufLoc, type, targetVA); break; case R_RELAX_TLS_IE_TO_LE: - Target->relaxTlsIeToLe(BufLoc, Type, TargetVA); + target->relaxTlsIeToLe(bufLoc, type, targetVA); break; case R_RELAX_TLS_LD_TO_LE: case R_RELAX_TLS_LD_TO_LE_ABS: - Target->relaxTlsLdToLe(BufLoc, Type, TargetVA); + target->relaxTlsLdToLe(bufLoc, type, targetVA); break; case R_RELAX_TLS_GD_TO_LE: case R_RELAX_TLS_GD_TO_LE_NEG: - Target->relaxTlsGdToLe(BufLoc, Type, TargetVA); + target->relaxTlsGdToLe(bufLoc, type, targetVA); break; case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: case R_RELAX_TLS_GD_TO_IE: case R_RELAX_TLS_GD_TO_IE_ABS: case R_RELAX_TLS_GD_TO_IE_GOT_OFF: case R_RELAX_TLS_GD_TO_IE_GOTPLT: - Target->relaxTlsGdToIe(BufLoc, Type, TargetVA); + target->relaxTlsGdToIe(bufLoc, type, targetVA); break; case R_PPC64_CALL: // If this is a call to __tls_get_addr, it may be part of a TLS // sequence that has been relaxed and turned into a nop. In this // case, we don't want to handle it as a call. - if (read32(BufLoc) == 0x60000000) // nop + if (read32(bufLoc) == 0x60000000) // nop break; // Patch a nop (0x60000000) to a ld. - if (Rel.Sym->NeedsTocRestore) { - if (BufLoc + 8 > BufEnd || read32(BufLoc + 4) != 0x60000000) { - error(getErrorLocation(BufLoc) + "call lacks nop, can't restore toc"); + if (rel.sym->needsTocRestore) { + if (bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) { + error(getErrorLocation(bufLoc) + "call lacks nop, can't restore toc"); break; } - write32(BufLoc + 4, 0xe8410018); // ld %r2, 24(%r1) + write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1) } - Target->relocateOne(BufLoc, Type, TargetVA); + target->relocateOne(bufLoc, type, targetVA); break; default: - Target->relocateOne(BufLoc, Type, TargetVA); + target->relocateOne(bufLoc, type, targetVA); break; } } @@ -979,44 +979,44 @@ // For each function-defining prologue, find any calls to __morestack, // and replace them with calls to __morestack_non_split. static void switchMorestackCallsToMorestackNonSplit( - DenseSet &Prologues, std::vector &MorestackCalls) { + DenseSet &prologues, std::vector &morestackCalls) { // If the target adjusted a function's prologue, all calls to // __morestack inside that function should be switched to // __morestack_non_split. - Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split"); - if (!MoreStackNonSplit) { + Symbol *moreStackNonSplit = symtab->find("__morestack_non_split"); + if (!moreStackNonSplit) { error("Mixing split-stack objects requires a definition of " "__morestack_non_split"); return; } // Sort both collections to compare addresses efficiently. - llvm::sort(MorestackCalls, [](const Relocation *L, const Relocation *R) { - return L->Offset < R->Offset; + llvm::sort(morestackCalls, [](const Relocation *l, const Relocation *r) { + return l->offset < r->offset; }); - std::vector Functions(Prologues.begin(), Prologues.end()); - llvm::sort(Functions, [](const Defined *L, const Defined *R) { - return L->Value < R->Value; + std::vector functions(prologues.begin(), prologues.end()); + llvm::sort(functions, [](const Defined *l, const Defined *r) { + return l->value < r->value; }); - auto It = MorestackCalls.begin(); - for (Defined *F : Functions) { + auto it = morestackCalls.begin(); + for (Defined *f : functions) { // Find the first call to __morestack within the function. - while (It != MorestackCalls.end() && (*It)->Offset < F->Value) - ++It; + while (it != morestackCalls.end() && (*it)->offset < f->value) + ++it; // Adjust all calls inside the function. - while (It != MorestackCalls.end() && (*It)->Offset < F->Value + F->Size) { - (*It)->Sym = MoreStackNonSplit; - ++It; + while (it != morestackCalls.end() && (*it)->offset < f->value + f->size) { + (*it)->sym = moreStackNonSplit; + ++it; } } } -static bool enclosingPrologueAttempted(uint64_t Offset, - const DenseSet &Prologues) { - for (Defined *F : Prologues) - if (F->Value <= Offset && Offset < F->Value + F->Size) +static bool enclosingPrologueAttempted(uint64_t offset, + const DenseSet &prologues) { + for (Defined *f : prologues) + if (f->value <= offset && offset < f->value + f->size) return true; return false; } @@ -1026,30 +1026,30 @@ // adjusted to ensure that the called function will have enough stack // available. Find those functions, and adjust their prologues. template -void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf, - uint8_t *End) { - if (!getFile()->SplitStack) +void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf, + uint8_t *end) { + if (!getFile()->splitStack) return; - DenseSet Prologues; - std::vector MorestackCalls; + DenseSet prologues; + std::vector morestackCalls; - for (Relocation &Rel : Relocations) { + for (Relocation &rel : relocations) { // Local symbols can't possibly be cross-calls, and should have been // resolved long before this line. - if (Rel.Sym->isLocal()) + if (rel.sym->isLocal()) continue; // Ignore calls into the split-stack api. - if (Rel.Sym->getName().startswith("__morestack")) { - if (Rel.Sym->getName().equals("__morestack")) - MorestackCalls.push_back(&Rel); + if (rel.sym->getName().startswith("__morestack")) { + if (rel.sym->getName().equals("__morestack")) + morestackCalls.push_back(&rel); continue; } // A relocation to non-function isn't relevant. Sometimes // __morestack is not marked as a function, so this check comes // after the name check. - if (Rel.Sym->Type != STT_FUNC) + if (rel.sym->type != STT_FUNC) continue; // If the callee's-file was compiled with split stack, nothing to do. In @@ -1057,117 +1057,117 @@ // being produced". So an "undefined" symbol might be provided by a shared // library. It is not possible to tell how such symbols were compiled, so be // conservative. - if (Defined *D = dyn_cast(Rel.Sym)) - if (InputSection *IS = cast_or_null(D->Section)) - if (!IS || !IS->getFile() || IS->getFile()->SplitStack) + if (Defined *d = dyn_cast(rel.sym)) + if (InputSection *isec = cast_or_null(d->section)) + if (!isec || !isec->getFile() || isec->getFile()->splitStack) continue; - if (enclosingPrologueAttempted(Rel.Offset, Prologues)) + if (enclosingPrologueAttempted(rel.offset, prologues)) continue; - if (Defined *F = getEnclosingFunction(Rel.Offset)) { - Prologues.insert(F); - if (Target->adjustPrologueForCrossSplitStack(Buf + getOffset(F->Value), - End, F->StOther)) + if (Defined *f = getEnclosingFunction(rel.offset)) { + prologues.insert(f); + if (target->adjustPrologueForCrossSplitStack(buf + getOffset(f->value), + end, f->stOther)) continue; - if (!getFile()->SomeNoSplitStack) - error(lld::toString(this) + ": " + F->getName() + - " (with -fsplit-stack) calls " + Rel.Sym->getName() + + if (!getFile()->someNoSplitStack) + error(lld::toString(this) + ": " + f->getName() + + " (with -fsplit-stack) calls " + rel.sym->getName() + " (without -fsplit-stack), but couldn't adjust its prologue"); } } - if (Target->NeedsMoreStackNonSplit) - switchMorestackCallsToMorestackNonSplit(Prologues, MorestackCalls); + if (target->needsMoreStackNonSplit) + switchMorestackCallsToMorestackNonSplit(prologues, morestackCalls); } -template void InputSection::writeTo(uint8_t *Buf) { - if (Type == SHT_NOBITS) +template void InputSection::writeTo(uint8_t *buf) { + if (type == SHT_NOBITS) return; - if (auto *S = dyn_cast(this)) { - S->writeTo(Buf + OutSecOff); + if (auto *s = dyn_cast(this)) { + s->writeTo(buf + outSecOff); return; } // If -r or --emit-relocs is given, then an InputSection // may be a relocation section. - if (Type == SHT_RELA) { - copyRelocations(Buf + OutSecOff, getDataAs()); + if (type == SHT_RELA) { + copyRelocations(buf + outSecOff, getDataAs()); return; } - if (Type == SHT_REL) { - copyRelocations(Buf + OutSecOff, getDataAs()); + if (type == SHT_REL) { + copyRelocations(buf + outSecOff, getDataAs()); return; } // If -r is given, we may have a SHT_GROUP section. - if (Type == SHT_GROUP) { - copyShtGroup(Buf + OutSecOff); + if (type == SHT_GROUP) { + copyShtGroup(buf + outSecOff); return; } // If this is a compressed section, uncompress section contents directly // to the buffer. - if (UncompressedSize >= 0) { - size_t Size = UncompressedSize; - if (Error E = zlib::uncompress(toStringRef(RawData), - (char *)(Buf + OutSecOff), Size)) + if (uncompressedSize >= 0) { + size_t size = uncompressedSize; + if (Error e = zlib::uncompress(toStringRef(rawData), + (char *)(buf + outSecOff), size)) fatal(toString(this) + - ": uncompress failed: " + llvm::toString(std::move(E))); - uint8_t *BufEnd = Buf + OutSecOff + Size; - relocate(Buf, BufEnd); + ": uncompress failed: " + llvm::toString(std::move(e))); + uint8_t *bufEnd = buf + outSecOff + size; + relocate(buf, bufEnd); return; } // Copy section contents from source object file to output file // and then apply relocations. - memcpy(Buf + OutSecOff, data().data(), data().size()); - uint8_t *BufEnd = Buf + OutSecOff + data().size(); - relocate(Buf, BufEnd); + memcpy(buf + outSecOff, data().data(), data().size()); + uint8_t *bufEnd = buf + outSecOff + data().size(); + relocate(buf, bufEnd); } -void InputSection::replace(InputSection *Other) { - Alignment = std::max(Alignment, Other->Alignment); +void InputSection::replace(InputSection *other) { + alignment = std::max(alignment, other->alignment); // When a section is replaced with another section that was allocated to // another partition, the replacement section (and its associated sections) // need to be placed in the main partition so that both partitions will be // able to access it. - if (Partition != Other->Partition) { - Partition = 1; - for (InputSection *IS : DependentSections) - IS->Partition = 1; + if (partition != other->partition) { + partition = 1; + for (InputSection *isec : dependentSections) + isec->partition = 1; } - Other->Repl = Repl; - Other->markDead(); + other->repl = repl; + other->markDead(); } template -EhInputSection::EhInputSection(ObjFile &F, - const typename ELFT::Shdr &Header, - StringRef Name) - : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) {} +EhInputSection::EhInputSection(ObjFile &f, + const typename ELFT::Shdr &header, + StringRef name) + : InputSectionBase(f, header, name, InputSectionBase::EHFrame) {} SyntheticSection *EhInputSection::getParent() const { - return cast_or_null(Parent); + return cast_or_null(parent); } // Returns the index of the first relocation that points to a region between // Begin and Begin+Size. template -static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef &Rels, - unsigned &RelocI) { +static unsigned getReloc(IntTy begin, IntTy size, const ArrayRef &rels, + unsigned &relocI) { // Start search from RelocI for fast access. That works because the // relocations are sorted in .eh_frame. - for (unsigned N = Rels.size(); RelocI < N; ++RelocI) { - const RelTy &Rel = Rels[RelocI]; - if (Rel.r_offset < Begin) + for (unsigned n = rels.size(); relocI < n; ++relocI) { + const RelTy &rel = rels[relocI]; + if (rel.r_offset < begin) continue; - if (Rel.r_offset < Begin + Size) - return RelocI; + if (rel.r_offset < begin + size) + return relocI; return -1; } return -1; @@ -1176,84 +1176,84 @@ // .eh_frame is a sequence of CIE or FDE records. // This function splits an input section into records and returns them. template void EhInputSection::split() { - if (AreRelocsRela) + if (areRelocsRela) split(relas()); else split(rels()); } template -void EhInputSection::split(ArrayRef Rels) { - unsigned RelI = 0; - for (size_t Off = 0, End = data().size(); Off != End;) { - size_t Size = readEhRecordSize(this, Off); - Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); +void EhInputSection::split(ArrayRef rels) { + unsigned relI = 0; + for (size_t off = 0, end = data().size(); off != end;) { + size_t size = readEhRecordSize(this, off); + pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI)); // The empty record is the end marker. - if (Size == 4) + if (size == 4) break; - Off += Size; + off += size; } } -static size_t findNull(StringRef S, size_t EntSize) { +static size_t findNull(StringRef s, size_t entSize) { // Optimize the common case. - if (EntSize == 1) - return S.find(0); + if (entSize == 1) + return s.find(0); - for (unsigned I = 0, N = S.size(); I != N; I += EntSize) { - const char *B = S.begin() + I; - if (std::all_of(B, B + EntSize, [](char C) { return C == 0; })) - return I; + for (unsigned i = 0, n = s.size(); i != n; i += entSize) { + const char *b = s.begin() + i; + if (std::all_of(b, b + entSize, [](char c) { return c == 0; })) + return i; } return StringRef::npos; } SyntheticSection *MergeInputSection::getParent() const { - return cast_or_null(Parent); + return cast_or_null(parent); } // Split SHF_STRINGS section. Such section is a sequence of // null-terminated strings. -void MergeInputSection::splitStrings(ArrayRef Data, size_t EntSize) { - size_t Off = 0; - bool IsAlloc = Flags & SHF_ALLOC; - StringRef S = toStringRef(Data); - - while (!S.empty()) { - size_t End = findNull(S, EntSize); - if (End == StringRef::npos) +void MergeInputSection::splitStrings(ArrayRef data, size_t entSize) { + size_t off = 0; + bool isAlloc = flags & SHF_ALLOC; + StringRef s = toStringRef(data); + + while (!s.empty()) { + size_t end = findNull(s, entSize); + if (end == StringRef::npos) fatal(toString(this) + ": string is not null terminated"); - size_t Size = End + EntSize; + size_t size = end + entSize; - Pieces.emplace_back(Off, xxHash64(S.substr(0, Size)), !IsAlloc); - S = S.substr(Size); - Off += Size; + pieces.emplace_back(off, xxHash64(s.substr(0, size)), !isAlloc); + s = s.substr(size); + off += size; } } // Split non-SHF_STRINGS section. Such section is a sequence of // fixed size records. -void MergeInputSection::splitNonStrings(ArrayRef Data, - size_t EntSize) { - size_t Size = Data.size(); - assert((Size % EntSize) == 0); - bool IsAlloc = Flags & SHF_ALLOC; +void MergeInputSection::splitNonStrings(ArrayRef data, + size_t entSize) { + size_t size = data.size(); + assert((size % entSize) == 0); + bool isAlloc = flags & SHF_ALLOC; - for (size_t I = 0; I != Size; I += EntSize) - Pieces.emplace_back(I, xxHash64(Data.slice(I, EntSize)), !IsAlloc); + for (size_t i = 0; i != size; i += entSize) + pieces.emplace_back(i, xxHash64(data.slice(i, entSize)), !isAlloc); } template -MergeInputSection::MergeInputSection(ObjFile &F, - const typename ELFT::Shdr &Header, - StringRef Name) - : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {} - -MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type, - uint64_t Entsize, ArrayRef Data, - StringRef Name) - : InputSectionBase(nullptr, Flags, Type, Entsize, /*Link*/ 0, /*Info*/ 0, - /*Alignment*/ Entsize, Data, Name, SectionBase::Merge) {} +MergeInputSection::MergeInputSection(ObjFile &f, + const typename ELFT::Shdr &header, + StringRef name) + : InputSectionBase(f, header, name, InputSectionBase::Merge) {} + +MergeInputSection::MergeInputSection(uint64_t flags, uint32_t type, + uint64_t entsize, ArrayRef data, + StringRef name) + : InputSectionBase(nullptr, flags, type, entsize, /*Link*/ 0, /*Info*/ 0, + /*Alignment*/ entsize, data, name, SectionBase::Merge) {} // This function is called after we obtain a complete list of input sections // that need to be linked. This is responsible to split section contents @@ -1262,35 +1262,35 @@ // Note that this function is called from parallelForEach. This must be // thread-safe (i.e. no memory allocation from the pools). void MergeInputSection::splitIntoPieces() { - assert(Pieces.empty()); + assert(pieces.empty()); - if (Flags & SHF_STRINGS) - splitStrings(data(), Entsize); + if (flags & SHF_STRINGS) + splitStrings(data(), entsize); else - splitNonStrings(data(), Entsize); + splitNonStrings(data(), entsize); } -SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) { - if (this->data().size() <= Offset) +SectionPiece *MergeInputSection::getSectionPiece(uint64_t offset) { + if (this->data().size() <= offset) fatal(toString(this) + ": offset is outside the section"); // If Offset is not at beginning of a section piece, it is not in the map. // In that case we need to do a binary search of the original section piece vector. - auto It = partition_point( - Pieces, [=](SectionPiece P) { return P.InputOff <= Offset; }); - return &It[-1]; + auto it = partition_point( + pieces, [=](SectionPiece p) { return p.inputOff <= offset; }); + return &it[-1]; } // Returns the offset in an output section for a given input offset. // Because contents of a mergeable section is not contiguous in output, // it is not just an addition to a base output offset. -uint64_t MergeInputSection::getParentOffset(uint64_t Offset) const { +uint64_t MergeInputSection::getParentOffset(uint64_t offset) const { // If Offset is not at beginning of a section piece, it is not in the map. // In that case we need to search from the original section piece vector. - const SectionPiece &Piece = - *(const_cast(this)->getSectionPiece (Offset)); - uint64_t Addend = Offset - Piece.InputOff; - return Piece.OutputOff + Addend; + const SectionPiece &piece = + *(const_cast(this)->getSectionPiece (offset)); + uint64_t addend = offset - piece.inputOff; + return piece.outputOff + addend; } template InputSection::InputSection(ObjFile &, const ELF32LE::Shdr &, Index: lld/trunk/ELF/LTO.h =================================================================== --- lld/trunk/ELF/LTO.h +++ lld/trunk/ELF/LTO.h @@ -45,16 +45,16 @@ BitcodeCompiler(); ~BitcodeCompiler(); - void add(BitcodeFile &F); + void add(BitcodeFile &f); std::vector compile(); private: - std::unique_ptr LTOObj; - std::vector> Buf; - std::vector> Files; - llvm::DenseSet UsedStartStop; - std::unique_ptr IndexFile; - llvm::DenseSet ThinIndices; + std::unique_ptr ltoObj; + std::vector> buf; + std::vector> files; + llvm::DenseSet usedStartStop; + std::unique_ptr indexFile; + llvm::DenseSet thinIndices; }; } // namespace elf } // namespace lld Index: lld/trunk/ELF/LTO.cpp =================================================================== --- lld/trunk/ELF/LTO.cpp +++ lld/trunk/ELF/LTO.cpp @@ -47,135 +47,135 @@ // Creates an empty file to store a list of object files for final // linking of distributed ThinLTO. -static std::unique_ptr openFile(StringRef File) { - std::error_code EC; - auto Ret = - llvm::make_unique(File, EC, sys::fs::OpenFlags::F_None); - if (EC) { - error("cannot open " + File + ": " + EC.message()); +static std::unique_ptr openFile(StringRef file) { + std::error_code ec; + auto ret = + llvm::make_unique(file, ec, sys::fs::OpenFlags::F_None); + if (ec) { + error("cannot open " + file + ": " + ec.message()); return nullptr; } - return Ret; + return ret; } -static std::string getThinLTOOutputFile(StringRef ModulePath) { - return lto::getThinLTOOutputFile(ModulePath, - Config->ThinLTOPrefixReplace.first, - Config->ThinLTOPrefixReplace.second); +static std::string getThinLTOOutputFile(StringRef modulePath) { + return lto::getThinLTOOutputFile(modulePath, + config->thinLTOPrefixReplace.first, + config->thinLTOPrefixReplace.second); } static lto::Config createConfig() { - lto::Config C; + lto::Config c; // LLD supports the new relocations and address-significance tables. - C.Options = initTargetOptionsFromCodeGenFlags(); - C.Options.RelaxELFRelocations = true; - C.Options.EmitAddrsig = true; + c.Options = initTargetOptionsFromCodeGenFlags(); + c.Options.RelaxELFRelocations = true; + c.Options.EmitAddrsig = true; // Always emit a section per function/datum with LTO. - C.Options.FunctionSections = true; - C.Options.DataSections = true; + c.Options.FunctionSections = true; + c.Options.DataSections = true; - if (Config->Relocatable) - C.RelocModel = None; - else if (Config->Pic) - C.RelocModel = Reloc::PIC_; + if (config->relocatable) + c.RelocModel = None; + else if (config->isPic) + c.RelocModel = Reloc::PIC_; else - C.RelocModel = Reloc::Static; + c.RelocModel = Reloc::Static; - C.CodeModel = getCodeModelFromCMModel(); - C.DisableVerify = Config->DisableVerify; - C.DiagHandler = diagnosticHandler; - C.OptLevel = Config->LTOO; - C.CPU = getCPUStr(); - C.MAttrs = getMAttrs(); - C.CGOptLevel = args::getCGOptLevel(Config->LTOO); + c.CodeModel = getCodeModelFromCMModel(); + c.DisableVerify = config->disableVerify; + c.DiagHandler = diagnosticHandler; + c.OptLevel = config->ltoo; + c.CPU = getCPUStr(); + c.MAttrs = getMAttrs(); + c.CGOptLevel = args::getCGOptLevel(config->ltoo); // Set up a custom pipeline if we've been asked to. - C.OptPipeline = Config->LTONewPmPasses; - C.AAPipeline = Config->LTOAAPipeline; + c.OptPipeline = config->ltoNewPmPasses; + c.AAPipeline = config->ltoAAPipeline; // Set up optimization remarks if we've been asked to. - C.RemarksFilename = Config->OptRemarksFilename; - C.RemarksPasses = Config->OptRemarksPasses; - C.RemarksWithHotness = Config->OptRemarksWithHotness; - C.RemarksFormat = Config->OptRemarksFormat; - - C.SampleProfile = Config->LTOSampleProfile; - C.UseNewPM = Config->LTONewPassManager; - C.DebugPassManager = Config->LTODebugPassManager; - C.DwoDir = Config->DwoDir; - - C.CSIRProfile = Config->LTOCSProfileFile; - C.RunCSIRInstr = Config->LTOCSProfileGenerate; - - if (Config->EmitLLVM) { - C.PostInternalizeModuleHook = [](size_t Task, const Module &M) { - if (std::unique_ptr OS = openFile(Config->OutputFile)) - WriteBitcodeToFile(M, *OS, false); + c.RemarksFilename = config->optRemarksFilename; + c.RemarksPasses = config->optRemarksPasses; + c.RemarksWithHotness = config->optRemarksWithHotness; + c.RemarksFormat = config->optRemarksFormat; + + c.SampleProfile = config->ltoSampleProfile; + c.UseNewPM = config->ltoNewPassManager; + c.DebugPassManager = config->ltoDebugPassManager; + c.DwoDir = config->dwoDir; + + c.CSIRProfile = config->ltoCSProfileFile; + c.RunCSIRInstr = config->ltoCSProfileGenerate; + + if (config->emitLLVM) { + c.PostInternalizeModuleHook = [](size_t task, const Module &m) { + if (std::unique_ptr os = openFile(config->outputFile)) + WriteBitcodeToFile(m, *os, false); return false; }; } - if (Config->SaveTemps) - checkError(C.addSaveTemps(Config->OutputFile.str() + ".", + if (config->saveTemps) + checkError(c.addSaveTemps(config->outputFile.str() + ".", /*UseInputModulePath*/ true)); - return C; + return c; } BitcodeCompiler::BitcodeCompiler() { // Initialize IndexFile. - if (!Config->ThinLTOIndexOnlyArg.empty()) - IndexFile = openFile(Config->ThinLTOIndexOnlyArg); + if (!config->thinLTOIndexOnlyArg.empty()) + indexFile = openFile(config->thinLTOIndexOnlyArg); // Initialize LTOObj. - lto::ThinBackend Backend; - if (Config->ThinLTOIndexOnly) { - auto OnIndexWrite = [&](StringRef S) { ThinIndices.erase(S); }; - Backend = lto::createWriteIndexesThinBackend( - Config->ThinLTOPrefixReplace.first, Config->ThinLTOPrefixReplace.second, - Config->ThinLTOEmitImportsFiles, IndexFile.get(), OnIndexWrite); - } else if (Config->ThinLTOJobs != -1U) { - Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs); + lto::ThinBackend backend; + if (config->thinLTOIndexOnly) { + auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); }; + backend = lto::createWriteIndexesThinBackend( + config->thinLTOPrefixReplace.first, config->thinLTOPrefixReplace.second, + config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite); + } else if (config->thinLTOJobs != -1U) { + backend = lto::createInProcessThinBackend(config->thinLTOJobs); } - LTOObj = llvm::make_unique(createConfig(), Backend, - Config->LTOPartitions); + ltoObj = llvm::make_unique(createConfig(), backend, + config->ltoPartitions); // Initialize UsedStartStop. - Symtab->forEachSymbol([&](Symbol *Sym) { - StringRef S = Sym->getName(); - for (StringRef Prefix : {"__start_", "__stop_"}) - if (S.startswith(Prefix)) - UsedStartStop.insert(S.substr(Prefix.size())); + symtab->forEachSymbol([&](Symbol *sym) { + StringRef s = sym->getName(); + for (StringRef prefix : {"__start_", "__stop_"}) + if (s.startswith(prefix)) + usedStartStop.insert(s.substr(prefix.size())); }); } BitcodeCompiler::~BitcodeCompiler() = default; -void BitcodeCompiler::add(BitcodeFile &F) { - lto::InputFile &Obj = *F.Obj; - bool IsExec = !Config->Shared && !Config->Relocatable; - - if (Config->ThinLTOIndexOnly) - ThinIndices.insert(Obj.getName()); - - ArrayRef Syms = F.getSymbols(); - ArrayRef ObjSyms = Obj.symbols(); - std::vector Resols(Syms.size()); +void BitcodeCompiler::add(BitcodeFile &f) { + lto::InputFile &obj = *f.obj; + bool isExec = !config->shared && !config->relocatable; + + if (config->thinLTOIndexOnly) + thinIndices.insert(obj.getName()); + + ArrayRef syms = f.getSymbols(); + ArrayRef objSyms = obj.symbols(); + std::vector resols(syms.size()); // Provide a resolution to the LTO API for each symbol. - for (size_t I = 0, E = Syms.size(); I != E; ++I) { - Symbol *Sym = Syms[I]; - const lto::InputFile::Symbol &ObjSym = ObjSyms[I]; - lto::SymbolResolution &R = Resols[I]; + for (size_t i = 0, e = syms.size(); i != e; ++i) { + Symbol *sym = syms[i]; + const lto::InputFile::Symbol &objSym = objSyms[i]; + lto::SymbolResolution &r = resols[i]; // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile // reports two symbols for module ASM defined. Without this check, lld // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. - R.Prevailing = !ObjSym.isUndefined() && Sym->File == &F; + r.Prevailing = !objSym.isUndefined() && sym->file == &f; // We ask LTO to preserve following global symbols: // 1) All symbols when doing relocatable link, so that them can be used @@ -183,121 +183,121 @@ // 2) Symbols that are used in regular objects. // 3) C named sections if we have corresponding __start_/__stop_ symbol. // 4) Symbols that are defined in bitcode files and used for dynamic linking. - R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj || - (R.Prevailing && Sym->includeInDynsym()) || - UsedStartStop.count(ObjSym.getSectionName()); - const auto *DR = dyn_cast(Sym); - R.FinalDefinitionInLinkageUnit = - (IsExec || Sym->Visibility != STV_DEFAULT) && DR && + r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj || + (r.Prevailing && sym->includeInDynsym()) || + usedStartStop.count(objSym.getSectionName()); + const auto *dr = dyn_cast(sym); + r.FinalDefinitionInLinkageUnit = + (isExec || sym->visibility != STV_DEFAULT) && dr && // Skip absolute symbols from ELF objects, otherwise PC-rel relocations // will be generated by for them, triggering linker errors. // Symbol section is always null for bitcode symbols, hence the check // for isElf(). Skip linker script defined symbols as well: they have // no File defined. - !(DR->Section == nullptr && (!Sym->File || Sym->File->isElf())); + !(dr->section == nullptr && (!sym->file || sym->file->isElf())); - if (R.Prevailing) - Sym->replace(Undefined{nullptr, Sym->getName(), STB_GLOBAL, STV_DEFAULT, - Sym->Type}); + if (r.Prevailing) + sym->replace(Undefined{nullptr, sym->getName(), STB_GLOBAL, STV_DEFAULT, + sym->type}); // We tell LTO to not apply interprocedural optimization for wrapped // (with --wrap) symbols because otherwise LTO would inline them while // their values are still not final. - R.LinkerRedefined = !Sym->CanInline; + r.LinkerRedefined = !sym->canInline; } - checkError(LTOObj->add(std::move(F.Obj), Resols)); + checkError(ltoObj->add(std::move(f.obj), resols)); } // If LazyObjFile has not been added to link, emit empty index files. // This is needed because this is what GNU gold plugin does and we have a // distributed build system that depends on that behavior. static void thinLTOCreateEmptyIndexFiles() { - for (LazyObjFile *F : LazyObjFiles) { - if (!isBitcode(F->MB)) + for (LazyObjFile *f : lazyObjFiles) { + if (!isBitcode(f->mb)) continue; - std::string Path = replaceThinLTOSuffix(getThinLTOOutputFile(F->getName())); - std::unique_ptr OS = openFile(Path + ".thinlto.bc"); - if (!OS) + std::string path = replaceThinLTOSuffix(getThinLTOOutputFile(f->getName())); + std::unique_ptr os = openFile(path + ".thinlto.bc"); + if (!os) continue; - ModuleSummaryIndex M(/*HaveGVs*/ false); - M.setSkipModuleByDistributedBackend(); - WriteIndexToFile(M, *OS); - if (Config->ThinLTOEmitImportsFiles) - openFile(Path + ".imports"); + ModuleSummaryIndex m(/*HaveGVs*/ false); + m.setSkipModuleByDistributedBackend(); + WriteIndexToFile(m, *os); + if (config->thinLTOEmitImportsFiles) + openFile(path + ".imports"); } } // Merge all the bitcode files we have seen, codegen the result // and return the resulting ObjectFile(s). std::vector BitcodeCompiler::compile() { - unsigned MaxTasks = LTOObj->getMaxTasks(); - Buf.resize(MaxTasks); - Files.resize(MaxTasks); + unsigned maxTasks = ltoObj->getMaxTasks(); + buf.resize(maxTasks); + files.resize(maxTasks); // The --thinlto-cache-dir option specifies the path to a directory in which // to cache native object files for ThinLTO incremental builds. If a path was // specified, configure LTO to use it as the cache directory. - lto::NativeObjectCache Cache; - if (!Config->ThinLTOCacheDir.empty()) - Cache = check( - lto::localCache(Config->ThinLTOCacheDir, - [&](size_t Task, std::unique_ptr MB) { - Files[Task] = std::move(MB); + lto::NativeObjectCache cache; + if (!config->thinLTOCacheDir.empty()) + cache = check( + lto::localCache(config->thinLTOCacheDir, + [&](size_t task, std::unique_ptr mb) { + files[task] = std::move(mb); })); - if (!BitcodeFiles.empty()) - checkError(LTOObj->run( - [&](size_t Task) { + if (!bitcodeFiles.empty()) + checkError(ltoObj->run( + [&](size_t task) { return llvm::make_unique( - llvm::make_unique(Buf[Task])); + llvm::make_unique(buf[task])); }, - Cache)); + cache)); // Emit empty index files for non-indexed files - for (StringRef S : ThinIndices) { - std::string Path = getThinLTOOutputFile(S); - openFile(Path + ".thinlto.bc"); - if (Config->ThinLTOEmitImportsFiles) - openFile(Path + ".imports"); + for (StringRef s : thinIndices) { + std::string path = getThinLTOOutputFile(s); + openFile(path + ".thinlto.bc"); + if (config->thinLTOEmitImportsFiles) + openFile(path + ".imports"); } - if (Config->ThinLTOIndexOnly) { + if (config->thinLTOIndexOnly) { thinLTOCreateEmptyIndexFiles(); - if (!Config->LTOObjPath.empty()) - saveBuffer(Buf[0], Config->LTOObjPath); + if (!config->ltoObjPath.empty()) + saveBuffer(buf[0], config->ltoObjPath); // ThinLTO with index only option is required to generate only the index // files. After that, we exit from linker and ThinLTO backend runs in a // distributed environment. - if (IndexFile) - IndexFile->close(); + if (indexFile) + indexFile->close(); return {}; } - if (!Config->ThinLTOCacheDir.empty()) - pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy); + if (!config->thinLTOCacheDir.empty()) + pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy); - if (!Config->LTOObjPath.empty()) { - saveBuffer(Buf[0], Config->LTOObjPath); - for (unsigned I = 1; I != MaxTasks; ++I) - saveBuffer(Buf[I], Config->LTOObjPath + Twine(I)); + if (!config->ltoObjPath.empty()) { + saveBuffer(buf[0], config->ltoObjPath); + for (unsigned i = 1; i != maxTasks; ++i) + saveBuffer(buf[i], config->ltoObjPath + Twine(i)); } - if (Config->SaveTemps) { - saveBuffer(Buf[0], Config->OutputFile + ".lto.o"); - for (unsigned I = 1; I != MaxTasks; ++I) - saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.o"); + if (config->saveTemps) { + saveBuffer(buf[0], config->outputFile + ".lto.o"); + for (unsigned i = 1; i != maxTasks; ++i) + saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); } - std::vector Ret; - for (unsigned I = 0; I != MaxTasks; ++I) - if (!Buf[I].empty()) - Ret.push_back(createObjectFile(MemoryBufferRef(Buf[I], "lto.tmp"))); - - for (std::unique_ptr &File : Files) - if (File) - Ret.push_back(createObjectFile(*File)); - return Ret; + std::vector ret; + for (unsigned i = 0; i != maxTasks; ++i) + if (!buf[i].empty()) + ret.push_back(createObjectFile(MemoryBufferRef(buf[i], "lto.tmp"))); + + for (std::unique_ptr &file : files) + if (file) + ret.push_back(createObjectFile(*file)); + return ret; } Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -38,29 +38,29 @@ // This represents an r-value in the linker script. struct ExprValue { - ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val, - const Twine &Loc) - : Sec(Sec), ForceAbsolute(ForceAbsolute), Val(Val), Loc(Loc.str()) {} + ExprValue(SectionBase *sec, bool forceAbsolute, uint64_t val, + const Twine &loc) + : sec(sec), forceAbsolute(forceAbsolute), val(val), loc(loc.str()) {} - ExprValue(uint64_t Val) : ExprValue(nullptr, false, Val, "") {} + ExprValue(uint64_t val) : ExprValue(nullptr, false, val, "") {} - bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; } + bool isAbsolute() const { return forceAbsolute || sec == nullptr; } uint64_t getValue() const; uint64_t getSecAddr() const; uint64_t getSectionOffset() const; // If a value is relative to a section, it has a non-null Sec. - SectionBase *Sec; + SectionBase *sec; // True if this expression is enclosed in ABSOLUTE(). // This flag affects the return value of getValue(). - bool ForceAbsolute; + bool forceAbsolute; - uint64_t Val; - uint64_t Alignment = 1; + uint64_t val; + uint64_t alignment = 1; // Original source location. Used for error messages. - std::string Loc; + std::string loc; }; // This represents an expression in the linker script. @@ -78,42 +78,42 @@ }; struct BaseCommand { - BaseCommand(int K) : Kind(K) {} - int Kind; + BaseCommand(int k) : kind(k) {} + int kind; }; // This represents ". = " or " = ". struct SymbolAssignment : BaseCommand { - SymbolAssignment(StringRef Name, Expr E, std::string Loc) - : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} + SymbolAssignment(StringRef name, Expr e, std::string loc) + : BaseCommand(AssignmentKind), name(name), expression(e), location(loc) {} - static bool classof(const BaseCommand *C) { - return C->Kind == AssignmentKind; + static bool classof(const BaseCommand *c) { + return c->kind == AssignmentKind; } // The LHS of an expression. Name is either a symbol name or ".". - StringRef Name; - Defined *Sym = nullptr; + StringRef name; + Defined *sym = nullptr; // The RHS of an expression. - Expr Expression; + Expr expression; // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN. - bool Provide = false; - bool Hidden = false; + bool provide = false; + bool hidden = false; // Holds file name and line number for error reporting. - std::string Location; + std::string location; // A string representation of this command. We use this for -Map. - std::string CommandString; + std::string commandString; // Address of this assignment command. - unsigned Addr; + unsigned addr; // Size of this assignment command. This is usually 0, but if // you move '.' this may be greater than 0. - unsigned Size; + unsigned size; }; // Linker scripts allow additional constraints to be put on ouput sections. @@ -126,83 +126,83 @@ // target memory. Instances of the struct are created by parsing the // MEMORY command. struct MemoryRegion { - MemoryRegion(StringRef Name, uint64_t Origin, uint64_t Length, uint32_t Flags, - uint32_t NegFlags) - : Name(Name), Origin(Origin), Length(Length), Flags(Flags), - NegFlags(NegFlags) {} - - std::string Name; - uint64_t Origin; - uint64_t Length; - uint32_t Flags; - uint32_t NegFlags; - uint64_t CurPos = 0; + MemoryRegion(StringRef name, uint64_t origin, uint64_t length, uint32_t flags, + uint32_t negFlags) + : name(name), origin(origin), length(length), flags(flags), + negFlags(negFlags) {} + + std::string name; + uint64_t origin; + uint64_t length; + uint32_t flags; + uint32_t negFlags; + uint64_t curPos = 0; }; // This struct represents one section match pattern in SECTIONS() command. // It can optionally have negative match pattern for EXCLUDED_FILE command. // Also it may be surrounded with SORT() command, so contains sorting rules. struct SectionPattern { - SectionPattern(StringMatcher &&Pat1, StringMatcher &&Pat2) - : ExcludedFilePat(Pat1), SectionPat(Pat2), - SortOuter(SortSectionPolicy::Default), - SortInner(SortSectionPolicy::Default) {} - - StringMatcher ExcludedFilePat; - StringMatcher SectionPat; - SortSectionPolicy SortOuter; - SortSectionPolicy SortInner; + SectionPattern(StringMatcher &&pat1, StringMatcher &&pat2) + : excludedFilePat(pat1), sectionPat(pat2), + sortOuter(SortSectionPolicy::Default), + sortInner(SortSectionPolicy::Default) {} + + StringMatcher excludedFilePat; + StringMatcher sectionPat; + SortSectionPolicy sortOuter; + SortSectionPolicy sortInner; }; struct InputSectionDescription : BaseCommand { - InputSectionDescription(StringRef FilePattern) - : BaseCommand(InputSectionKind), FilePat(FilePattern) {} + InputSectionDescription(StringRef filePattern) + : BaseCommand(InputSectionKind), filePat(filePattern) {} - static bool classof(const BaseCommand *C) { - return C->Kind == InputSectionKind; + static bool classof(const BaseCommand *c) { + return c->kind == InputSectionKind; } - StringMatcher FilePat; + StringMatcher filePat; // Input sections that matches at least one of SectionPatterns // will be associated with this InputSectionDescription. - std::vector SectionPatterns; + std::vector sectionPatterns; - std::vector Sections; + std::vector sections; // Temporary record of synthetic ThunkSection instances and the pass that // they were created in. This is used to insert newly created ThunkSections // into Sections at the end of a createThunks() pass. - std::vector> ThunkSections; + std::vector> thunkSections; }; // Represents BYTE(), SHORT(), LONG(), or QUAD(). struct ByteCommand : BaseCommand { - ByteCommand(Expr E, unsigned Size, std::string CommandString) - : BaseCommand(ByteKind), CommandString(CommandString), Expression(E), - Size(Size) {} + ByteCommand(Expr e, unsigned size, std::string commandString) + : BaseCommand(ByteKind), commandString(commandString), expression(e), + size(size) {} - static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; } + static bool classof(const BaseCommand *c) { return c->kind == ByteKind; } // Keeps string representing the command. Used for -Map" is perhaps better. - std::string CommandString; + std::string commandString; - Expr Expression; + Expr expression; // This is just an offset of this assignment command in the output section. - unsigned Offset; + unsigned offset; // Size of this data command. - unsigned Size; + unsigned size; }; struct PhdrsCommand { - StringRef Name; - unsigned Type = llvm::ELF::PT_NULL; - bool HasFilehdr = false; - bool HasPhdrs = false; - llvm::Optional Flags; - Expr LMAExpr = nullptr; + StringRef name; + unsigned type = llvm::ELF::PT_NULL; + bool hasFilehdr = false; + bool hasPhdrs = false; + llvm::Optional flags; + Expr lmaExpr = nullptr; }; class LinkerScript final { @@ -211,35 +211,35 @@ // not be used outside of the scope of a call to the above functions. struct AddressState { AddressState(); - uint64_t ThreadBssOffset = 0; - OutputSection *OutSec = nullptr; - MemoryRegion *MemRegion = nullptr; - MemoryRegion *LMARegion = nullptr; - uint64_t LMAOffset = 0; + uint64_t threadBssOffset = 0; + OutputSection *outSec = nullptr; + MemoryRegion *memRegion = nullptr; + MemoryRegion *lmaRegion = nullptr; + uint64_t lmaOffset = 0; }; - llvm::DenseMap NameToOutputSection; + llvm::DenseMap nameToOutputSection; - void addSymbol(SymbolAssignment *Cmd); - void assignSymbol(SymbolAssignment *Cmd, bool InSec); - void setDot(Expr E, const Twine &Loc, bool InSec); - void expandOutputSection(uint64_t Size); - void expandMemoryRegions(uint64_t Size); + void addSymbol(SymbolAssignment *cmd); + void assignSymbol(SymbolAssignment *cmd, bool inSec); + void setDot(Expr e, const Twine &loc, bool inSec); + void expandOutputSection(uint64_t size); + void expandMemoryRegions(uint64_t size); std::vector computeInputSections(const InputSectionDescription *); - std::vector createInputSectionList(OutputSection &Cmd); + std::vector createInputSectionList(OutputSection &cmd); - std::vector getPhdrIndices(OutputSection *Sec); + std::vector getPhdrIndices(OutputSection *sec); - MemoryRegion *findMemoryRegion(OutputSection *Sec); + MemoryRegion *findMemoryRegion(OutputSection *sec); - void switchTo(OutputSection *Sec); - uint64_t advance(uint64_t Size, unsigned Align); - void output(InputSection *Sec); + void switchTo(OutputSection *sec); + uint64_t advance(uint64_t size, unsigned align); + void output(InputSection *sec); - void assignOffsets(OutputSection *Sec); + void assignOffsets(OutputSection *sec); // Ctx captures the local AddressState and makes it accessible // deliberately. This is needed as there are some cases where we cannot just @@ -247,21 +247,21 @@ // script parser. // This should remain a plain pointer as its lifetime is smaller than // LinkerScript. - AddressState *Ctx = nullptr; + AddressState *ctx = nullptr; - OutputSection *Aether; + OutputSection *aether; - uint64_t Dot; + uint64_t dot; public: - OutputSection *createOutputSection(StringRef Name, StringRef Location); - OutputSection *getOrCreateOutputSection(StringRef Name); + OutputSection *createOutputSection(StringRef name, StringRef location); + OutputSection *getOrCreateOutputSection(StringRef name); - bool hasPhdrsCommands() { return !PhdrsCommands.empty(); } - uint64_t getDot() { return Dot; } - void discard(ArrayRef V); + bool hasPhdrsCommands() { return !phdrsCommands.empty(); } + uint64_t getDot() { return dot; } + void discard(ArrayRef v); - ExprValue getSymbolValue(StringRef Name, const Twine &Loc); + ExprValue getSymbolValue(StringRef name, const Twine &loc); void addOrphanSections(); void adjustSectionsBeforeSorting(); @@ -270,9 +270,9 @@ std::vector createPhdrs(); bool needsInterpSection(); - bool shouldKeep(InputSectionBase *S); + bool shouldKeep(InputSectionBase *s); void assignAddresses(); - void allocateHeaders(std::vector &Phdrs); + void allocateHeaders(std::vector &phdrs); void processSectionCommands(); void declareSymbols(); @@ -280,31 +280,31 @@ void processInsertCommands(); // SECTIONS command list. - std::vector SectionCommands; + std::vector sectionCommands; // PHDRS command list. - std::vector PhdrsCommands; + std::vector phdrsCommands; - bool HasSectionsCommand = false; - bool ErrorOnMissingSection = false; + bool hasSectionsCommand = false; + bool errorOnMissingSection = false; // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. - std::vector KeptSections; + std::vector keptSections; // A map from memory region name to a memory region descriptor. - llvm::MapVector MemoryRegions; + llvm::MapVector memoryRegions; // A list of symbols referenced by the script. - std::vector ReferencedSymbols; + std::vector referencedSymbols; // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need // to be inserted into SECTIONS commands list. - llvm::DenseMap> InsertAfterCommands; - llvm::DenseMap> InsertBeforeCommands; + llvm::DenseMap> insertAfterCommands; + llvm::DenseMap> insertBeforeCommands; }; -extern LinkerScript *Script; +extern LinkerScript *script; } // end namespace elf } // end namespace lld Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -46,26 +46,26 @@ using namespace lld; using namespace lld::elf; -LinkerScript *elf::Script; +LinkerScript *elf::script; -static uint64_t getOutputSectionVA(SectionBase *InputSec, StringRef Loc) { - if (OutputSection *OS = InputSec->getOutputSection()) - return OS->Addr; - error(Loc + ": unable to evaluate expression: input section " + - InputSec->Name + " has no output section assigned"); +static uint64_t getOutputSectionVA(SectionBase *inputSec, StringRef loc) { + if (OutputSection *os = inputSec->getOutputSection()) + return os->addr; + error(loc + ": unable to evaluate expression: input section " + + inputSec->name + " has no output section assigned"); return 0; } uint64_t ExprValue::getValue() const { - if (Sec) - return alignTo(Sec->getOffset(Val) + getOutputSectionVA(Sec, Loc), - Alignment); - return alignTo(Val, Alignment); + if (sec) + return alignTo(sec->getOffset(val) + getOutputSectionVA(sec, loc), + alignment); + return alignTo(val, alignment); } uint64_t ExprValue::getSecAddr() const { - if (Sec) - return Sec->getOffset(0) + getOutputSectionVA(Sec, Loc); + if (sec) + return sec->getOffset(0) + getOutputSectionVA(sec, loc); return 0; } @@ -73,100 +73,100 @@ // If the alignment is trivial, we don't have to compute the full // value to know the offset. This allows this function to succeed in // cases where the output section is not yet known. - if (Alignment == 1 && (!Sec || !Sec->getOutputSection())) - return Val; + if (alignment == 1 && (!sec || !sec->getOutputSection())) + return val; return getValue() - getSecAddr(); } -OutputSection *LinkerScript::createOutputSection(StringRef Name, - StringRef Location) { - OutputSection *&SecRef = NameToOutputSection[Name]; - OutputSection *Sec; - if (SecRef && SecRef->Location.empty()) { +OutputSection *LinkerScript::createOutputSection(StringRef name, + StringRef location) { + OutputSection *&secRef = nameToOutputSection[name]; + OutputSection *sec; + if (secRef && secRef->location.empty()) { // There was a forward reference. - Sec = SecRef; + sec = secRef; } else { - Sec = make(Name, SHT_PROGBITS, 0); - if (!SecRef) - SecRef = Sec; - } - Sec->Location = Location; - return Sec; + sec = make(name, SHT_PROGBITS, 0); + if (!secRef) + secRef = sec; + } + sec->location = location; + return sec; } -OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) { - OutputSection *&CmdRef = NameToOutputSection[Name]; - if (!CmdRef) - CmdRef = make(Name, SHT_PROGBITS, 0); - return CmdRef; +OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) { + OutputSection *&cmdRef = nameToOutputSection[name]; + if (!cmdRef) + cmdRef = make(name, SHT_PROGBITS, 0); + return cmdRef; } // Expands the memory region by the specified size. -static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size, - StringRef RegionName, StringRef SecName) { - MemRegion->CurPos += Size; - uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin; - if (NewSize > MemRegion->Length) - error("section '" + SecName + "' will not fit in region '" + RegionName + - "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes"); +static void expandMemoryRegion(MemoryRegion *memRegion, uint64_t size, + StringRef regionName, StringRef secName) { + memRegion->curPos += size; + uint64_t newSize = memRegion->curPos - memRegion->origin; + if (newSize > memRegion->length) + error("section '" + secName + "' will not fit in region '" + regionName + + "': overflowed by " + Twine(newSize - memRegion->length) + " bytes"); } -void LinkerScript::expandMemoryRegions(uint64_t Size) { - if (Ctx->MemRegion) - expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, - Ctx->OutSec->Name); +void LinkerScript::expandMemoryRegions(uint64_t size) { + if (ctx->memRegion) + expandMemoryRegion(ctx->memRegion, size, ctx->memRegion->name, + ctx->outSec->name); // Only expand the LMARegion if it is different from MemRegion. - if (Ctx->LMARegion && Ctx->MemRegion != Ctx->LMARegion) - expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name, - Ctx->OutSec->Name); + if (ctx->lmaRegion && ctx->memRegion != ctx->lmaRegion) + expandMemoryRegion(ctx->lmaRegion, size, ctx->lmaRegion->name, + ctx->outSec->name); } -void LinkerScript::expandOutputSection(uint64_t Size) { - Ctx->OutSec->Size += Size; - expandMemoryRegions(Size); +void LinkerScript::expandOutputSection(uint64_t size) { + ctx->outSec->size += size; + expandMemoryRegions(size); } -void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { - uint64_t Val = E().getValue(); - if (Val < Dot && InSec) - error(Loc + ": unable to move location counter backward for: " + - Ctx->OutSec->Name); +void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) { + uint64_t val = e().getValue(); + if (val < dot && inSec) + error(loc + ": unable to move location counter backward for: " + + ctx->outSec->name); // Update to location counter means update to section size. - if (InSec) - expandOutputSection(Val - Dot); + if (inSec) + expandOutputSection(val - dot); - Dot = Val; + dot = val; } // Used for handling linker symbol assignments, for both finalizing // their values and doing early declarations. Returns true if symbol // should be defined from linker script. -static bool shouldDefineSym(SymbolAssignment *Cmd) { - if (Cmd->Name == ".") +static bool shouldDefineSym(SymbolAssignment *cmd) { + if (cmd->name == ".") return false; - if (!Cmd->Provide) + if (!cmd->provide) return true; // If a symbol was in PROVIDE(), we need to define it only // when it is a referenced undefined symbol. - Symbol *B = Symtab->find(Cmd->Name); - if (B && !B->isDefined()) + Symbol *b = symtab->find(cmd->name); + if (b && !b->isDefined()) return true; return false; } // This function is called from processSectionCommands, // while we are fixing the output section layout. -void LinkerScript::addSymbol(SymbolAssignment *Cmd) { - if (!shouldDefineSym(Cmd)) +void LinkerScript::addSymbol(SymbolAssignment *cmd) { + if (!shouldDefineSym(cmd)) return; // Define a symbol. - ExprValue Value = Cmd->Expression(); - SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; - uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; + ExprValue value = cmd->expression(); + SectionBase *sec = value.isAbsolute() ? nullptr : value.sec; + uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT; // When this function is called, section addresses have not been // fixed yet. So, we may or may not know the value of the RHS @@ -179,73 +179,73 @@ // We want to set symbol values early if we can. This allows us to // use symbols as variables in linker scripts. Doing so allows us to // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`. - uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); + uint64_t symValue = value.sec ? 0 : value.getValue(); - Defined New(nullptr, Cmd->Name, STB_GLOBAL, Visibility, STT_NOTYPE, SymValue, - 0, Sec); + Defined New(nullptr, cmd->name, STB_GLOBAL, visibility, STT_NOTYPE, symValue, + 0, sec); - Symbol *Sym = Symtab->insert(Cmd->Name); - Sym->mergeProperties(New); - Sym->replace(New); - Cmd->Sym = cast(Sym); + Symbol *sym = symtab->insert(cmd->name); + sym->mergeProperties(New); + sym->replace(New); + cmd->sym = cast(sym); } // This function is called from LinkerScript::declareSymbols. // It creates a placeholder symbol if needed. -static void declareSymbol(SymbolAssignment *Cmd) { - if (!shouldDefineSym(Cmd)) +static void declareSymbol(SymbolAssignment *cmd) { + if (!shouldDefineSym(cmd)) return; - uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; - Defined New(nullptr, Cmd->Name, STB_GLOBAL, Visibility, STT_NOTYPE, 0, 0, + uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT; + Defined New(nullptr, cmd->name, STB_GLOBAL, visibility, STT_NOTYPE, 0, 0, nullptr); // We can't calculate final value right now. - Symbol *Sym = Symtab->insert(Cmd->Name); - Sym->mergeProperties(New); - Sym->replace(New); - - Cmd->Sym = cast(Sym); - Cmd->Provide = false; - Sym->ScriptDefined = true; + Symbol *sym = symtab->insert(cmd->name); + sym->mergeProperties(New); + sym->replace(New); + + cmd->sym = cast(sym); + cmd->provide = false; + sym->scriptDefined = true; } // This method is used to handle INSERT AFTER statement. Here we rebuild // the list of script commands to mix sections inserted into. void LinkerScript::processInsertCommands() { - std::vector V; - auto Insert = [&](std::vector &From) { - V.insert(V.end(), From.begin(), From.end()); - From.clear(); + std::vector v; + auto insert = [&](std::vector &from) { + v.insert(v.end(), from.begin(), from.end()); + from.clear(); }; - for (BaseCommand *Base : SectionCommands) { - if (auto *OS = dyn_cast(Base)) { - Insert(InsertBeforeCommands[OS->Name]); - V.push_back(Base); - Insert(InsertAfterCommands[OS->Name]); + for (BaseCommand *base : sectionCommands) { + if (auto *os = dyn_cast(base)) { + insert(insertBeforeCommands[os->name]); + v.push_back(base); + insert(insertAfterCommands[os->name]); continue; } - V.push_back(Base); + v.push_back(base); } - for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands}) - for (const std::pair> &P : Cmds) - if (!P.second.empty()) - error("unable to INSERT AFTER/BEFORE " + P.first + + for (auto &cmds : {insertBeforeCommands, insertAfterCommands}) + for (const std::pair> &p : cmds) + if (!p.second.empty()) + error("unable to INSERT AFTER/BEFORE " + p.first + ": section not defined"); - SectionCommands = std::move(V); + sectionCommands = std::move(v); } // Symbols defined in script should not be inlined by LTO. At the same time // we don't know their final values until late stages of link. Here we scan // over symbol assignment commands and create placeholder symbols if needed. void LinkerScript::declareSymbols() { - assert(!Ctx); - for (BaseCommand *Base : SectionCommands) { - if (auto *Cmd = dyn_cast(Base)) { - declareSymbol(Cmd); + assert(!ctx); + for (BaseCommand *base : sectionCommands) { + if (auto *cmd = dyn_cast(base)) { + declareSymbol(cmd); continue; } @@ -253,75 +253,75 @@ // we can't say for sure if it is going to be included or not. // Skip such sections for now. Improve the checks if we ever // need symbols from that sections to be declared early. - auto *Sec = cast(Base); - if (Sec->Constraint != ConstraintKind::NoConstraint) + auto *sec = cast(base); + if (sec->constraint != ConstraintKind::NoConstraint) continue; - for (BaseCommand *Base2 : Sec->SectionCommands) - if (auto *Cmd = dyn_cast(Base2)) - declareSymbol(Cmd); + for (BaseCommand *base2 : sec->sectionCommands) + if (auto *cmd = dyn_cast(base2)) + declareSymbol(cmd); } } // This function is called from assignAddresses, while we are // fixing the output section addresses. This function is supposed // to set the final value for a given symbol assignment. -void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { - if (Cmd->Name == ".") { - setDot(Cmd->Expression, Cmd->Location, InSec); +void LinkerScript::assignSymbol(SymbolAssignment *cmd, bool inSec) { + if (cmd->name == ".") { + setDot(cmd->expression, cmd->location, inSec); return; } - if (!Cmd->Sym) + if (!cmd->sym) return; - ExprValue V = Cmd->Expression(); - if (V.isAbsolute()) { - Cmd->Sym->Section = nullptr; - Cmd->Sym->Value = V.getValue(); + ExprValue v = cmd->expression(); + if (v.isAbsolute()) { + cmd->sym->section = nullptr; + cmd->sym->value = v.getValue(); } else { - Cmd->Sym->Section = V.Sec; - Cmd->Sym->Value = V.getSectionOffset(); + cmd->sym->section = v.sec; + cmd->sym->value = v.getSectionOffset(); } } -static std::string getFilename(InputFile *File) { - if (!File) +static std::string getFilename(InputFile *file) { + if (!file) return ""; - if (File->ArchiveName.empty()) - return File->getName(); - return (File->ArchiveName + "(" + File->getName() + ")").str(); + if (file->archiveName.empty()) + return file->getName(); + return (file->archiveName + "(" + file->getName() + ")").str(); } -bool LinkerScript::shouldKeep(InputSectionBase *S) { - if (KeptSections.empty()) +bool LinkerScript::shouldKeep(InputSectionBase *s) { + if (keptSections.empty()) return false; - std::string Filename = getFilename(S->File); - for (InputSectionDescription *ID : KeptSections) - if (ID->FilePat.match(Filename)) - for (SectionPattern &P : ID->SectionPatterns) - if (P.SectionPat.match(S->Name)) + std::string filename = getFilename(s->file); + for (InputSectionDescription *id : keptSections) + if (id->filePat.match(filename)) + for (SectionPattern &p : id->sectionPatterns) + if (p.sectionPat.match(s->name)) return true; return false; } // A helper function for the SORT() command. static std::function -getComparator(SortSectionPolicy K) { - switch (K) { +getComparator(SortSectionPolicy k) { + switch (k) { case SortSectionPolicy::Alignment: - return [](InputSectionBase *A, InputSectionBase *B) { + return [](InputSectionBase *a, InputSectionBase *b) { // ">" is not a mistake. Sections with larger alignments are placed // before sections with smaller alignments in order to reduce the // amount of padding necessary. This is compatible with GNU. - return A->Alignment > B->Alignment; + return a->alignment > b->alignment; }; case SortSectionPolicy::Name: - return [](InputSectionBase *A, InputSectionBase *B) { - return A->Name < B->Name; + return [](InputSectionBase *a, InputSectionBase *b) { + return a->name < b->name; }; case SortSectionPolicy::Priority: - return [](InputSectionBase *A, InputSectionBase *B) { - return getPriority(A->Name) < getPriority(B->Name); + return [](InputSectionBase *a, InputSectionBase *b) { + return getPriority(a->name) < getPriority(b->name); }; default: llvm_unreachable("unknown sort policy"); @@ -329,22 +329,22 @@ } // A helper function for the SORT() command. -static bool matchConstraints(ArrayRef Sections, - ConstraintKind Kind) { - if (Kind == ConstraintKind::NoConstraint) +static bool matchConstraints(ArrayRef sections, + ConstraintKind kind) { + if (kind == ConstraintKind::NoConstraint) return true; - bool IsRW = llvm::any_of( - Sections, [](InputSection *Sec) { return Sec->Flags & SHF_WRITE; }); + bool isRW = llvm::any_of( + sections, [](InputSection *sec) { return sec->flags & SHF_WRITE; }); - return (IsRW && Kind == ConstraintKind::ReadWrite) || - (!IsRW && Kind == ConstraintKind::ReadOnly); + return (isRW && kind == ConstraintKind::ReadWrite) || + (!isRW && kind == ConstraintKind::ReadOnly); } -static void sortSections(MutableArrayRef Vec, - SortSectionPolicy K) { - if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None) - llvm::stable_sort(Vec, getComparator(K)); +static void sortSections(MutableArrayRef vec, + SortSectionPolicy k) { + if (k != SortSectionPolicy::Default && k != SortSectionPolicy::None) + llvm::stable_sort(vec, getComparator(k)); } // Sort sections as instructed by SORT-family commands and --sort-section @@ -358,29 +358,29 @@ // --sort-section is handled as an inner SORT command. // 3. If one SORT command is given, and if it is SORT_NONE, don't sort. // 4. If no SORT command is given, sort according to --sort-section. -static void sortInputSections(MutableArrayRef Vec, - const SectionPattern &Pat) { - if (Pat.SortOuter == SortSectionPolicy::None) +static void sortInputSections(MutableArrayRef vec, + const SectionPattern &pat) { + if (pat.sortOuter == SortSectionPolicy::None) return; - if (Pat.SortInner == SortSectionPolicy::Default) - sortSections(Vec, Config->SortSection); + if (pat.sortInner == SortSectionPolicy::Default) + sortSections(vec, config->sortSection); else - sortSections(Vec, Pat.SortInner); - sortSections(Vec, Pat.SortOuter); + sortSections(vec, pat.sortInner); + sortSections(vec, pat.sortOuter); } // Compute and remember which sections the InputSectionDescription matches. std::vector -LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { - std::vector Ret; +LinkerScript::computeInputSections(const InputSectionDescription *cmd) { + std::vector ret; // Collects all sections that satisfy constraints of Cmd. - for (const SectionPattern &Pat : Cmd->SectionPatterns) { - size_t SizeBefore = Ret.size(); + for (const SectionPattern &pat : cmd->sectionPatterns) { + size_t sizeBefore = ret.size(); - for (InputSectionBase *Sec : InputSections) { - if (!Sec->isLive() || Sec->Assigned) + for (InputSectionBase *sec : inputSections) { + if (!sec->isLive() || sec->assigned) continue; // For -emit-relocs we have to ignore entries like @@ -388,59 +388,59 @@ // which are common because they are in the default bfd script. // We do not ignore SHT_REL[A] linker-synthesized sections here because // want to support scripts that do custom layout for them. - if (auto *IS = dyn_cast(Sec)) - if (IS->getRelocatedSection()) + if (auto *isec = dyn_cast(sec)) + if (isec->getRelocatedSection()) continue; - std::string Filename = getFilename(Sec->File); - if (!Cmd->FilePat.match(Filename) || - Pat.ExcludedFilePat.match(Filename) || - !Pat.SectionPat.match(Sec->Name)) + std::string filename = getFilename(sec->file); + if (!cmd->filePat.match(filename) || + pat.excludedFilePat.match(filename) || + !pat.sectionPat.match(sec->name)) continue; // It is safe to assume that Sec is an InputSection // because mergeable or EH input sections have already been // handled and eliminated. - Ret.push_back(cast(Sec)); - Sec->Assigned = true; + ret.push_back(cast(sec)); + sec->assigned = true; } - sortInputSections(MutableArrayRef(Ret).slice(SizeBefore), - Pat); + sortInputSections(MutableArrayRef(ret).slice(sizeBefore), + pat); } - return Ret; + return ret; } -void LinkerScript::discard(ArrayRef V) { - for (InputSection *S : V) { - if (S == In.ShStrTab || S == Main->RelaDyn || S == Main->RelrDyn) - error("discarding " + S->Name + " section is not allowed"); +void LinkerScript::discard(ArrayRef v) { + for (InputSection *s : v) { + if (s == in.shStrTab || s == mainPart->relaDyn || s == mainPart->relrDyn) + error("discarding " + s->name + " section is not allowed"); // You can discard .hash and .gnu.hash sections by linker scripts. Since // they are synthesized sections, we need to handle them differently than // other regular sections. - if (S == Main->GnuHashTab) - Main->GnuHashTab = nullptr; - if (S == Main->HashTab) - Main->HashTab = nullptr; - - S->Assigned = false; - S->markDead(); - discard(S->DependentSections); + if (s == mainPart->gnuHashTab) + mainPart->gnuHashTab = nullptr; + if (s == mainPart->hashTab) + mainPart->hashTab = nullptr; + + s->assigned = false; + s->markDead(); + discard(s->dependentSections); } } std::vector -LinkerScript::createInputSectionList(OutputSection &OutCmd) { - std::vector Ret; +LinkerScript::createInputSectionList(OutputSection &outCmd) { + std::vector ret; - for (BaseCommand *Base : OutCmd.SectionCommands) { - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Sections = computeInputSections(Cmd); - Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end()); + for (BaseCommand *base : outCmd.sectionCommands) { + if (auto *cmd = dyn_cast(base)) { + cmd->sections = computeInputSections(cmd); + ret.insert(ret.end(), cmd->sections.begin(), cmd->sections.end()); } } - return Ret; + return ret; } void LinkerScript::processSectionCommands() { @@ -453,34 +453,34 @@ // To handle that, create a dummy aether section that fills the void before // the linker scripts switches to another section. It has an index of one // which will map to whatever the first actual section is. - Aether = make("", 0, SHF_ALLOC); - Aether->SectionIndex = 1; + aether = make("", 0, SHF_ALLOC); + aether->sectionIndex = 1; // Ctx captures the local AddressState and makes it accessible deliberately. // This is needed as there are some cases where we cannot just // thread the current state through to a lambda function created by the // script parser. - auto Deleter = make_unique(); - Ctx = Deleter.get(); - Ctx->OutSec = Aether; + auto deleter = make_unique(); + ctx = deleter.get(); + ctx->outSec = aether; - size_t I = 0; + size_t i = 0; // Add input sections to output sections. - for (BaseCommand *Base : SectionCommands) { + for (BaseCommand *base : sectionCommands) { // Handle symbol assignments outside of any output section. - if (auto *Cmd = dyn_cast(Base)) { - addSymbol(Cmd); + if (auto *cmd = dyn_cast(base)) { + addSymbol(cmd); continue; } - if (auto *Sec = dyn_cast(Base)) { - std::vector V = createInputSectionList(*Sec); + if (auto *sec = dyn_cast(base)) { + std::vector v = createInputSectionList(*sec); // The output section name `/DISCARD/' is special. // Any input section assigned to it is discarded. - if (Sec->Name == "/DISCARD/") { - discard(V); - Sec->SectionCommands.clear(); + if (sec->name == "/DISCARD/") { + discard(v); + sec->sectionCommands.clear(); continue; } @@ -491,61 +491,61 @@ // // Because we'll iterate over SectionCommands many more times, the easy // way to "make it as if it wasn't present" is to make it empty. - if (!matchConstraints(V, Sec->Constraint)) { - for (InputSectionBase *S : V) - S->Assigned = false; - Sec->SectionCommands.clear(); + if (!matchConstraints(v, sec->constraint)) { + for (InputSectionBase *s : v) + s->assigned = false; + sec->sectionCommands.clear(); continue; } // A directive may contain symbol definitions like this: // ".foo : { ...; bar = .; }". Handle them. - for (BaseCommand *Base : Sec->SectionCommands) - if (auto *OutCmd = dyn_cast(Base)) - addSymbol(OutCmd); + for (BaseCommand *base : sec->sectionCommands) + if (auto *outCmd = dyn_cast(base)) + addSymbol(outCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the // given value is larger or smaller than the original section alignment. - if (Sec->SubalignExpr) { - uint32_t Subalign = Sec->SubalignExpr().getValue(); - for (InputSectionBase *S : V) - S->Alignment = Subalign; + if (sec->subalignExpr) { + uint32_t subalign = sec->subalignExpr().getValue(); + for (InputSectionBase *s : v) + s->alignment = subalign; } // Add input sections to an output section. - for (InputSection *S : V) - Sec->addSection(S); + for (InputSection *s : v) + sec->addSection(s); - Sec->SectionIndex = I++; - if (Sec->Noload) - Sec->Type = SHT_NOBITS; - if (Sec->NonAlloc) - Sec->Flags &= ~(uint64_t)SHF_ALLOC; + sec->sectionIndex = i++; + if (sec->noload) + sec->type = SHT_NOBITS; + if (sec->nonAlloc) + sec->flags &= ~(uint64_t)SHF_ALLOC; } } - Ctx = nullptr; + ctx = nullptr; } -static OutputSection *findByName(ArrayRef Vec, - StringRef Name) { - for (BaseCommand *Base : Vec) - if (auto *Sec = dyn_cast(Base)) - if (Sec->Name == Name) - return Sec; +static OutputSection *findByName(ArrayRef vec, + StringRef name) { + for (BaseCommand *base : vec) + if (auto *sec = dyn_cast(base)) + if (sec->name == name) + return sec; return nullptr; } -static OutputSection *createSection(InputSectionBase *IS, - StringRef OutsecName) { - OutputSection *Sec = Script->createOutputSection(OutsecName, ""); - Sec->addSection(cast(IS)); - return Sec; +static OutputSection *createSection(InputSectionBase *isec, + StringRef outsecName) { + OutputSection *sec = script->createOutputSection(outsecName, ""); + sec->addSection(cast(isec)); + return sec; } static OutputSection * -addInputSec(StringMap> &Map, - InputSectionBase *IS, StringRef OutsecName) { +addInputSec(StringMap> &map, + InputSectionBase *isec, StringRef outsecName) { // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r // option is given. A section with SHT_GROUP defines a "section group", and // its members have SHF_GROUP attribute. Usually these flags have already been @@ -553,8 +553,8 @@ // However, for the -r option, we want to pass through all section groups // as-is because adding/removing members or merging them with other groups // change their semantics. - if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP)) - return createSection(IS, OutsecName); + if (isec->type == SHT_GROUP || (isec->flags & SHF_GROUP)) + return createSection(isec, outsecName); // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have // relocation sections .rela.foo and .rela.bar for example. Most tools do @@ -562,25 +562,25 @@ // should combine these relocation sections into single output. // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any // other REL[A] sections created by linker itself. - if (!isa(IS) && - (IS->Type == SHT_REL || IS->Type == SHT_RELA)) { - auto *Sec = cast(IS); - OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); + if (!isa(isec) && + (isec->type == SHT_REL || isec->type == SHT_RELA)) { + auto *sec = cast(isec); + OutputSection *out = sec->getRelocatedSection()->getOutputSection(); - if (Out->RelocationSection) { - Out->RelocationSection->addSection(Sec); + if (out->relocationSection) { + out->relocationSection->addSection(sec); return nullptr; } - Out->RelocationSection = createSection(IS, OutsecName); - return Out->RelocationSection; + out->relocationSection = createSection(isec, outsecName); + return out->relocationSection; } // When control reaches here, mergeable sections have already been merged into // synthetic sections. For relocatable case we want to create one output // section per syntetic section so that they have a valid sh_entsize. - if (Config->Relocatable && (IS->Flags & SHF_MERGE)) - return createSection(IS, OutsecName); + if (config->relocatable && (isec->flags & SHF_MERGE)) + return createSection(isec, outsecName); // The ELF spec just says // ---------------------------------------------------------------- @@ -624,161 +624,161 @@ // // Given the above issues, we instead merge sections by name and error on // incompatible types and flags. - TinyPtrVector &V = Map[OutsecName]; - for (OutputSection *Sec : V) { - if (Sec->Partition != IS->Partition) + TinyPtrVector &v = map[outsecName]; + for (OutputSection *sec : v) { + if (sec->partition != isec->partition) continue; - Sec->addSection(cast(IS)); + sec->addSection(cast(isec)); return nullptr; } - OutputSection *Sec = createSection(IS, OutsecName); - V.push_back(Sec); - return Sec; + OutputSection *sec = createSection(isec, outsecName); + v.push_back(sec); + return sec; } // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections() { - StringMap> Map; - std::vector V; + StringMap> map; + std::vector v; - auto Add = [&](InputSectionBase *S) { - if (!S->isLive() || S->Parent) + auto add = [&](InputSectionBase *s) { + if (!s->isLive() || s->parent) return; - StringRef Name = getOutputSectionName(S); + StringRef name = getOutputSectionName(s); - if (Config->OrphanHandling == OrphanHandlingPolicy::Error) - error(toString(S) + " is being placed in '" + Name + "'"); - else if (Config->OrphanHandling == OrphanHandlingPolicy::Warn) - warn(toString(S) + " is being placed in '" + Name + "'"); + if (config->orphanHandling == OrphanHandlingPolicy::Error) + error(toString(s) + " is being placed in '" + name + "'"); + else if (config->orphanHandling == OrphanHandlingPolicy::Warn) + warn(toString(s) + " is being placed in '" + name + "'"); - if (OutputSection *Sec = findByName(SectionCommands, Name)) { - Sec->addSection(cast(S)); + if (OutputSection *sec = findByName(sectionCommands, name)) { + sec->addSection(cast(s)); return; } - if (OutputSection *OS = addInputSec(Map, S, Name)) - V.push_back(OS); - assert(S->getOutputSection()->SectionIndex == UINT32_MAX); + if (OutputSection *os = addInputSec(map, s, name)) + v.push_back(os); + assert(s->getOutputSection()->sectionIndex == UINT32_MAX); }; // For futher --emit-reloc handling code we need target output section // to be created before we create relocation output section, so we want // to create target sections first. We do not want priority handling // for synthetic sections because them are special. - for (InputSectionBase *IS : InputSections) { - if (auto *Sec = dyn_cast(IS)) - if (InputSectionBase *Rel = Sec->getRelocatedSection()) - if (auto *RelIS = dyn_cast_or_null(Rel->Parent)) - Add(RelIS); - Add(IS); + for (InputSectionBase *isec : inputSections) { + if (auto *sec = dyn_cast(isec)) + if (InputSectionBase *rel = sec->getRelocatedSection()) + if (auto *relIS = dyn_cast_or_null(rel->parent)) + add(relIS); + add(isec); } // If no SECTIONS command was given, we should insert sections commands // before others, so that we can handle scripts which refers them, // for example: "foo = ABSOLUTE(ADDR(.text)));". // When SECTIONS command is present we just add all orphans to the end. - if (HasSectionsCommand) - SectionCommands.insert(SectionCommands.end(), V.begin(), V.end()); + if (hasSectionsCommand) + sectionCommands.insert(sectionCommands.end(), v.begin(), v.end()); else - SectionCommands.insert(SectionCommands.begin(), V.begin(), V.end()); + sectionCommands.insert(sectionCommands.begin(), v.begin(), v.end()); } -uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) { - bool IsTbss = - (Ctx->OutSec->Flags & SHF_TLS) && Ctx->OutSec->Type == SHT_NOBITS; - uint64_t Start = IsTbss ? Dot + Ctx->ThreadBssOffset : Dot; - Start = alignTo(Start, Alignment); - uint64_t End = Start + Size; +uint64_t LinkerScript::advance(uint64_t size, unsigned alignment) { + bool isTbss = + (ctx->outSec->flags & SHF_TLS) && ctx->outSec->type == SHT_NOBITS; + uint64_t start = isTbss ? dot + ctx->threadBssOffset : dot; + start = alignTo(start, alignment); + uint64_t end = start + size; - if (IsTbss) - Ctx->ThreadBssOffset = End - Dot; + if (isTbss) + ctx->threadBssOffset = end - dot; else - Dot = End; - return End; + dot = end; + return end; } -void LinkerScript::output(InputSection *S) { - assert(Ctx->OutSec == S->getParent()); - uint64_t Before = advance(0, 1); - uint64_t Pos = advance(S->getSize(), S->Alignment); - S->OutSecOff = Pos - S->getSize() - Ctx->OutSec->Addr; +void LinkerScript::output(InputSection *s) { + assert(ctx->outSec == s->getParent()); + uint64_t before = advance(0, 1); + uint64_t pos = advance(s->getSize(), s->alignment); + s->outSecOff = pos - s->getSize() - ctx->outSec->addr; // Update output section size after adding each section. This is so that // SIZEOF works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } - expandOutputSection(Pos - Before); + expandOutputSection(pos - before); } -void LinkerScript::switchTo(OutputSection *Sec) { - Ctx->OutSec = Sec; +void LinkerScript::switchTo(OutputSection *sec) { + ctx->outSec = sec; - uint64_t Before = advance(0, 1); - Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment); - expandMemoryRegions(Ctx->OutSec->Addr - Before); + uint64_t before = advance(0, 1); + ctx->outSec->addr = advance(0, ctx->outSec->alignment); + expandMemoryRegions(ctx->outSec->addr - before); } // This function searches for a memory region to place the given output // section in. If found, a pointer to the appropriate memory region is // returned. Otherwise, a nullptr is returned. -MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) { +MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *sec) { // If a memory region name was specified in the output section command, // then try to find that region first. - if (!Sec->MemoryRegionName.empty()) { - if (MemoryRegion *M = MemoryRegions.lookup(Sec->MemoryRegionName)) - return M; - error("memory region '" + Sec->MemoryRegionName + "' not declared"); + if (!sec->memoryRegionName.empty()) { + if (MemoryRegion *m = memoryRegions.lookup(sec->memoryRegionName)) + return m; + error("memory region '" + sec->memoryRegionName + "' not declared"); return nullptr; } // If at least one memory region is defined, all sections must // belong to some memory region. Otherwise, we don't need to do // anything for memory regions. - if (MemoryRegions.empty()) + if (memoryRegions.empty()) return nullptr; // See if a region can be found by matching section flags. - for (auto &Pair : MemoryRegions) { - MemoryRegion *M = Pair.second; - if ((M->Flags & Sec->Flags) && (M->NegFlags & Sec->Flags) == 0) - return M; + for (auto &pair : memoryRegions) { + MemoryRegion *m = pair.second; + if ((m->flags & sec->flags) && (m->negFlags & sec->flags) == 0) + return m; } // Otherwise, no suitable region was found. - if (Sec->Flags & SHF_ALLOC) - error("no memory region specified for section '" + Sec->Name + "'"); + if (sec->flags & SHF_ALLOC) + error("no memory region specified for section '" + sec->name + "'"); return nullptr; } -static OutputSection *findFirstSection(PhdrEntry *Load) { - for (OutputSection *Sec : OutputSections) - if (Sec->PtLoad == Load) - return Sec; +static OutputSection *findFirstSection(PhdrEntry *load) { + for (OutputSection *sec : outputSections) + if (sec->ptLoad == load) + return sec; return nullptr; } // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). -void LinkerScript::assignOffsets(OutputSection *Sec) { - if (!(Sec->Flags & SHF_ALLOC)) - Dot = 0; +void LinkerScript::assignOffsets(OutputSection *sec) { + if (!(sec->flags & SHF_ALLOC)) + dot = 0; - Ctx->MemRegion = Sec->MemRegion; - Ctx->LMARegion = Sec->LMARegion; - if (Ctx->MemRegion) - Dot = Ctx->MemRegion->CurPos; + ctx->memRegion = sec->memRegion; + ctx->lmaRegion = sec->lmaRegion; + if (ctx->memRegion) + dot = ctx->memRegion->curPos; - if ((Sec->Flags & SHF_ALLOC) && Sec->AddrExpr) - setDot(Sec->AddrExpr, Sec->Location, false); + if ((sec->flags & SHF_ALLOC) && sec->addrExpr) + setDot(sec->addrExpr, sec->location, false); - switchTo(Sec); + switchTo(sec); - if (Sec->LMAExpr) - Ctx->LMAOffset = Sec->LMAExpr().getValue() - Dot; + if (sec->lmaExpr) + ctx->lmaOffset = sec->lmaExpr().getValue() - dot; - if (MemoryRegion *MR = Sec->LMARegion) - Ctx->LMAOffset = MR->CurPos - Dot; + if (MemoryRegion *mr = sec->lmaRegion) + ctx->lmaOffset = mr->curPos - dot; // If neither AT nor AT> is specified for an allocatable section, the linker // will set the LMA such that the difference between VMA and LMA for the @@ -786,71 +786,71 @@ // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html // This, however, should only be done by the first "non-header" section // in the segment. - if (PhdrEntry *L = Ctx->OutSec->PtLoad) - if (Sec == findFirstSection(L)) - L->LMAOffset = Ctx->LMAOffset; + if (PhdrEntry *l = ctx->outSec->ptLoad) + if (sec == findFirstSection(l)) + l->lmaOffset = ctx->lmaOffset; // We can call this method multiple times during the creation of // thunks and want to start over calculation each time. - Sec->Size = 0; + sec->size = 0; // We visited SectionsCommands from processSectionCommands to // layout sections. Now, we visit SectionsCommands again to fix // section offsets. - for (BaseCommand *Base : Sec->SectionCommands) { + for (BaseCommand *base : sec->sectionCommands) { // This handles the assignments to symbol or to the dot. - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Addr = Dot; - assignSymbol(Cmd, true); - Cmd->Size = Dot - Cmd->Addr; + if (auto *cmd = dyn_cast(base)) { + cmd->addr = dot; + assignSymbol(cmd, true); + cmd->size = dot - cmd->addr; continue; } // Handle BYTE(), SHORT(), LONG(), or QUAD(). - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Offset = Dot - Ctx->OutSec->Addr; - Dot += Cmd->Size; - expandOutputSection(Cmd->Size); + if (auto *cmd = dyn_cast(base)) { + cmd->offset = dot - ctx->outSec->addr; + dot += cmd->size; + expandOutputSection(cmd->size); continue; } // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. - for (InputSection *Sec : cast(Base)->Sections) - output(Sec); + for (InputSection *sec : cast(base)->sections) + output(sec); } } -static bool isDiscardable(OutputSection &Sec) { - if (Sec.Name == "/DISCARD/") +static bool isDiscardable(OutputSection &sec) { + if (sec.name == "/DISCARD/") return true; // We do not remove empty sections that are explicitly // assigned to any segment. - if (!Sec.Phdrs.empty()) + if (!sec.phdrs.empty()) return false; // We do not want to remove OutputSections with expressions that reference // symbols even if the OutputSection is empty. We want to ensure that the // expressions can be evaluated and report an error if they cannot. - if (Sec.ExpressionsUseSymbols) + if (sec.expressionsUseSymbols) return false; // OutputSections may be referenced by name in ADDR and LOADADDR expressions, // as an empty Section can has a valid VMA and LMA we keep the OutputSection // to maintain the integrity of the other Expression. - if (Sec.UsedInExpression) + if (sec.usedInExpression) return false; - for (BaseCommand *Base : Sec.SectionCommands) { - if (auto Cmd = dyn_cast(Base)) + for (BaseCommand *base : sec.sectionCommands) { + if (auto cmd = dyn_cast(base)) // Don't create empty output sections just for unreferenced PROVIDE // symbols. - if (Cmd->Name != "." && !Cmd->Sym) + if (cmd->name != "." && !cmd->sym) continue; - if (!isa(*Base)) + if (!isa(*base)) return false; } return true; @@ -877,35 +877,35 @@ // The other option is to pick flags that minimize the impact the section // will have on the rest of the linker. That is why we copy the flags from // the previous sections. Only a few flags are needed to keep the impact low. - uint64_t Flags = SHF_ALLOC; + uint64_t flags = SHF_ALLOC; - for (BaseCommand *&Cmd : SectionCommands) { - auto *Sec = dyn_cast(Cmd); - if (!Sec) + for (BaseCommand *&cmd : sectionCommands) { + auto *sec = dyn_cast(cmd); + if (!sec) continue; // Handle align (e.g. ".foo : ALIGN(16) { ... }"). - if (Sec->AlignExpr) - Sec->Alignment = - std::max(Sec->Alignment, Sec->AlignExpr().getValue()); + if (sec->alignExpr) + sec->alignment = + std::max(sec->alignment, sec->alignExpr().getValue()); // The input section might have been removed (if it was an empty synthetic // section), but we at least know the flags. - if (Sec->HasInputSections) - Flags = Sec->Flags; + if (sec->hasInputSections) + flags = sec->flags; // We do not want to keep any special flags for output section // in case it is empty. - bool IsEmpty = getInputSections(Sec).empty(); - if (IsEmpty) - Sec->Flags = Flags & ((Sec->NonAlloc ? 0 : (uint64_t)SHF_ALLOC) | + bool isEmpty = getInputSections(sec).empty(); + if (isEmpty) + sec->flags = flags & ((sec->nonAlloc ? 0 : (uint64_t)SHF_ALLOC) | SHF_WRITE | SHF_EXECINSTR); - if (IsEmpty && isDiscardable(*Sec)) { - Sec->markDead(); - Cmd = nullptr; - } else if (!Sec->isLive()) { - Sec->markLive(); + if (isEmpty && isDiscardable(*sec)) { + sec->markDead(); + cmd = nullptr; + } else if (!sec->isLive()) { + sec->markLive(); } } @@ -915,20 +915,20 @@ // clutter the output. // We instead remove trivially empty sections. The bfd linker seems even // more aggressive at removing them. - llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; }); + llvm::erase_if(sectionCommands, [&](BaseCommand *base) { return !base; }); } void LinkerScript::adjustSectionsAfterSorting() { // Try and find an appropriate memory region to assign offsets in. - for (BaseCommand *Base : SectionCommands) { - if (auto *Sec = dyn_cast(Base)) { - if (!Sec->LMARegionName.empty()) { - if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName)) - Sec->LMARegion = M; + for (BaseCommand *base : sectionCommands) { + if (auto *sec = dyn_cast(base)) { + if (!sec->lmaRegionName.empty()) { + if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName)) + sec->lmaRegion = m; else - error("memory region '" + Sec->LMARegionName + "' not declared"); + error("memory region '" + sec->lmaRegionName + "' not declared"); } - Sec->MemRegion = findMemoryRegion(Sec); + sec->memRegion = findMemoryRegion(sec); } } @@ -938,38 +938,38 @@ // Below is an example of such linker script: // PHDRS { seg PT_LOAD; } // SECTIONS { .aaa : { *(.aaa) } } - std::vector DefPhdrs; - auto FirstPtLoad = llvm::find_if(PhdrsCommands, [](const PhdrsCommand &Cmd) { - return Cmd.Type == PT_LOAD; + std::vector defPhdrs; + auto firstPtLoad = llvm::find_if(phdrsCommands, [](const PhdrsCommand &cmd) { + return cmd.type == PT_LOAD; }); - if (FirstPtLoad != PhdrsCommands.end()) - DefPhdrs.push_back(FirstPtLoad->Name); + if (firstPtLoad != phdrsCommands.end()) + defPhdrs.push_back(firstPtLoad->name); // Walk the commands and propagate the program headers to commands that don't // explicitly specify them. - for (BaseCommand *Base : SectionCommands) { - auto *Sec = dyn_cast(Base); - if (!Sec) + for (BaseCommand *base : sectionCommands) { + auto *sec = dyn_cast(base); + if (!sec) continue; - if (Sec->Phdrs.empty()) { + if (sec->phdrs.empty()) { // To match the bfd linker script behaviour, only propagate program // headers to sections that are allocated. - if (Sec->Flags & SHF_ALLOC) - Sec->Phdrs = DefPhdrs; + if (sec->flags & SHF_ALLOC) + sec->phdrs = defPhdrs; } else { - DefPhdrs = Sec->Phdrs; + defPhdrs = sec->phdrs; } } } -static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) { +static uint64_t computeBase(uint64_t min, bool allocateHeaders) { // If there is no SECTIONS or if the linkerscript is explicit about program // headers, do our best to allocate them. - if (!Script->HasSectionsCommand || AllocateHeaders) + if (!script->hasSectionsCommand || allocateHeaders) return 0; // Otherwise only allocate program headers if that would not add a page. - return alignDown(Min, Config->MaxPageSize); + return alignDown(min, config->maxPageSize); } // Try to find an address for the file and program headers output sections, @@ -983,120 +983,120 @@ // // If there isn't enough space for these sections, we'll remove them from the // PT_LOAD segment, and we'll also remove the PT_PHDR segment. -void LinkerScript::allocateHeaders(std::vector &Phdrs) { - uint64_t Min = std::numeric_limits::max(); - for (OutputSection *Sec : OutputSections) - if (Sec->Flags & SHF_ALLOC) - Min = std::min(Min, Sec->Addr); - - auto It = llvm::find_if( - Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; }); - if (It == Phdrs.end()) +void LinkerScript::allocateHeaders(std::vector &phdrs) { + uint64_t min = std::numeric_limits::max(); + for (OutputSection *sec : outputSections) + if (sec->flags & SHF_ALLOC) + min = std::min(min, sec->addr); + + auto it = llvm::find_if( + phdrs, [](const PhdrEntry *e) { return e->p_type == PT_LOAD; }); + if (it == phdrs.end()) return; - PhdrEntry *FirstPTLoad = *It; + PhdrEntry *firstPTLoad = *it; - bool HasExplicitHeaders = - llvm::any_of(PhdrsCommands, [](const PhdrsCommand &Cmd) { - return Cmd.HasPhdrs || Cmd.HasFilehdr; + bool hasExplicitHeaders = + llvm::any_of(phdrsCommands, [](const PhdrsCommand &cmd) { + return cmd.hasPhdrs || cmd.hasFilehdr; }); - bool Paged = !Config->Omagic && !Config->Nmagic; - uint64_t HeaderSize = getHeaderSize(); - if ((Paged || HasExplicitHeaders) && - HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) { - Min = alignDown(Min - HeaderSize, Config->MaxPageSize); - Out::ElfHeader->Addr = Min; - Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size; + bool paged = !config->omagic && !config->nmagic; + uint64_t headerSize = getHeaderSize(); + if ((paged || hasExplicitHeaders) && + headerSize <= min - computeBase(min, hasExplicitHeaders)) { + min = alignDown(min - headerSize, config->maxPageSize); + Out::elfHeader->addr = min; + Out::programHeaders->addr = min + Out::elfHeader->size; return; } // Error if we were explicitly asked to allocate headers. - if (HasExplicitHeaders) + if (hasExplicitHeaders) error("could not allocate headers"); - Out::ElfHeader->PtLoad = nullptr; - Out::ProgramHeaders->PtLoad = nullptr; - FirstPTLoad->FirstSec = findFirstSection(FirstPTLoad); + Out::elfHeader->ptLoad = nullptr; + Out::programHeaders->ptLoad = nullptr; + firstPTLoad->firstSec = findFirstSection(firstPTLoad); - llvm::erase_if(Phdrs, - [](const PhdrEntry *E) { return E->p_type == PT_PHDR; }); + llvm::erase_if(phdrs, + [](const PhdrEntry *e) { return e->p_type == PT_PHDR; }); } LinkerScript::AddressState::AddressState() { - for (auto &MRI : Script->MemoryRegions) { - MemoryRegion *MR = MRI.second; - MR->CurPos = MR->Origin; + for (auto &mri : script->memoryRegions) { + MemoryRegion *mr = mri.second; + mr->curPos = mr->origin; } } static uint64_t getInitialDot() { // By default linker scripts use an initial value of 0 for '.', // but prefer -image-base if set. - if (Script->HasSectionsCommand) - return Config->ImageBase ? *Config->ImageBase : 0; + if (script->hasSectionsCommand) + return config->imageBase ? *config->imageBase : 0; - uint64_t StartAddr = UINT64_MAX; + uint64_t startAddr = UINT64_MAX; // The Sections with -T
have been sorted in order of ascending // address. We must lower StartAddr if the lowest -T
as // calls to setDot() must be monotonically increasing. - for (auto &KV : Config->SectionStartMap) - StartAddr = std::min(StartAddr, KV.second); - return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize()); + for (auto &kv : config->sectionStartMap) + startAddr = std::min(startAddr, kv.second); + return std::min(startAddr, target->getImageBase() + elf::getHeaderSize()); } // Here we assign addresses as instructed by linker script SECTIONS // sub-commands. Doing that allows us to use final VA values, so here // we also handle rest commands like symbol assignments and ASSERTs. void LinkerScript::assignAddresses() { - Dot = getInitialDot(); + dot = getInitialDot(); - auto Deleter = make_unique(); - Ctx = Deleter.get(); - ErrorOnMissingSection = true; - switchTo(Aether); - - for (BaseCommand *Base : SectionCommands) { - if (auto *Cmd = dyn_cast(Base)) { - Cmd->Addr = Dot; - assignSymbol(Cmd, false); - Cmd->Size = Dot - Cmd->Addr; + auto deleter = make_unique(); + ctx = deleter.get(); + errorOnMissingSection = true; + switchTo(aether); + + for (BaseCommand *base : sectionCommands) { + if (auto *cmd = dyn_cast(base)) { + cmd->addr = dot; + assignSymbol(cmd, false); + cmd->size = dot - cmd->addr; continue; } - assignOffsets(cast(Base)); + assignOffsets(cast(base)); } - Ctx = nullptr; + ctx = nullptr; } // Creates program headers as instructed by PHDRS linker script command. std::vector LinkerScript::createPhdrs() { - std::vector Ret; + std::vector ret; // Process PHDRS and FILEHDR keywords because they are not // real output sections and cannot be added in the following loop. - for (const PhdrsCommand &Cmd : PhdrsCommands) { - PhdrEntry *Phdr = make(Cmd.Type, Cmd.Flags ? *Cmd.Flags : PF_R); + for (const PhdrsCommand &cmd : phdrsCommands) { + PhdrEntry *phdr = make(cmd.type, cmd.flags ? *cmd.flags : PF_R); - if (Cmd.HasFilehdr) - Phdr->add(Out::ElfHeader); - if (Cmd.HasPhdrs) - Phdr->add(Out::ProgramHeaders); - - if (Cmd.LMAExpr) { - Phdr->p_paddr = Cmd.LMAExpr().getValue(); - Phdr->HasLMA = true; + if (cmd.hasFilehdr) + phdr->add(Out::elfHeader); + if (cmd.hasPhdrs) + phdr->add(Out::programHeaders); + + if (cmd.lmaExpr) { + phdr->p_paddr = cmd.lmaExpr().getValue(); + phdr->hasLMA = true; } - Ret.push_back(Phdr); + ret.push_back(phdr); } // Add output sections to program headers. - for (OutputSection *Sec : OutputSections) { + for (OutputSection *sec : outputSections) { // Assign headers specified by linker script - for (size_t Id : getPhdrIndices(Sec)) { - Ret[Id]->add(Sec); - if (!PhdrsCommands[Id].Flags.hasValue()) - Ret[Id]->p_flags |= Sec->getPhdrFlags(); + for (size_t id : getPhdrIndices(sec)) { + ret[id]->add(sec); + if (!phdrsCommands[id].flags.hasValue()) + ret[id]->p_flags |= sec->getPhdrFlags(); } } - return Ret; + return ret; } // Returns true if we should emit an .interp section. @@ -1105,54 +1105,54 @@ // no PT_INTERP is there, there's no place to emit an // .interp, so we don't do that in that case. bool LinkerScript::needsInterpSection() { - if (PhdrsCommands.empty()) + if (phdrsCommands.empty()) return true; - for (PhdrsCommand &Cmd : PhdrsCommands) - if (Cmd.Type == PT_INTERP) + for (PhdrsCommand &cmd : phdrsCommands) + if (cmd.type == PT_INTERP) return true; return false; } -ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) { - if (Name == ".") { - if (Ctx) - return {Ctx->OutSec, false, Dot - Ctx->OutSec->Addr, Loc}; - error(Loc + ": unable to get location counter value"); +ExprValue LinkerScript::getSymbolValue(StringRef name, const Twine &loc) { + if (name == ".") { + if (ctx) + return {ctx->outSec, false, dot - ctx->outSec->addr, loc}; + error(loc + ": unable to get location counter value"); return 0; } - if (Symbol *Sym = Symtab->find(Name)) { - if (auto *DS = dyn_cast(Sym)) - return {DS->Section, false, DS->Value, Loc}; - if (isa(Sym)) - if (!ErrorOnMissingSection) - return {nullptr, false, 0, Loc}; + if (Symbol *sym = symtab->find(name)) { + if (auto *ds = dyn_cast(sym)) + return {ds->section, false, ds->value, loc}; + if (isa(sym)) + if (!errorOnMissingSection) + return {nullptr, false, 0, loc}; } - error(Loc + ": symbol not found: " + Name); + error(loc + ": symbol not found: " + name); return 0; } // Returns the index of the segment named Name. -static Optional getPhdrIndex(ArrayRef Vec, - StringRef Name) { - for (size_t I = 0; I < Vec.size(); ++I) - if (Vec[I].Name == Name) - return I; +static Optional getPhdrIndex(ArrayRef vec, + StringRef name) { + for (size_t i = 0; i < vec.size(); ++i) + if (vec[i].name == name) + return i; return None; } // Returns indices of ELF headers containing specific section. Each index is a // zero based number of ELF header listed within PHDRS {} script block. -std::vector LinkerScript::getPhdrIndices(OutputSection *Cmd) { - std::vector Ret; +std::vector LinkerScript::getPhdrIndices(OutputSection *cmd) { + std::vector ret; - for (StringRef S : Cmd->Phdrs) { - if (Optional Idx = getPhdrIndex(PhdrsCommands, S)) - Ret.push_back(*Idx); - else if (S != "NONE") - error(Cmd->Location + ": section header '" + S + + for (StringRef s : cmd->phdrs) { + if (Optional idx = getPhdrIndex(phdrsCommands, s)) + ret.push_back(*idx); + else if (s != "NONE") + error(cmd->location + ": section header '" + s + "' is not listed in PHDRS"); } - return Ret; + return ret; } Index: lld/trunk/ELF/MapFile.cpp =================================================================== --- lld/trunk/ELF/MapFile.cpp +++ lld/trunk/ELF/MapFile.cpp @@ -39,65 +39,65 @@ using SymbolMapTy = DenseMap>; -static const std::string Indent8 = " "; // 8 spaces -static const std::string Indent16 = " "; // 16 spaces +static const std::string indent8 = " "; // 8 spaces +static const std::string indent16 = " "; // 16 spaces // Print out the first three columns of a line. -static void writeHeader(raw_ostream &OS, uint64_t VMA, uint64_t LMA, - uint64_t Size, uint64_t Align) { - if (Config->Is64) - OS << format("%16llx %16llx %8llx %5lld ", VMA, LMA, Size, Align); +static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma, + uint64_t size, uint64_t align) { + if (config->is64) + os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align); else - OS << format("%8llx %8llx %8llx %5lld ", VMA, LMA, Size, Align); + os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align); } // Returns a list of all symbols that we want to print out. static std::vector getSymbols() { - std::vector V; - for (InputFile *File : ObjectFiles) - for (Symbol *B : File->getSymbols()) - if (auto *DR = dyn_cast(B)) - if (!DR->isSection() && DR->Section && DR->Section->isLive() && - (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss)) - V.push_back(DR); - return V; + std::vector v; + for (InputFile *file : objectFiles) + for (Symbol *b : file->getSymbols()) + if (auto *dr = dyn_cast(b)) + if (!dr->isSection() && dr->section && dr->section->isLive() && + (dr->file == file || dr->needsPltAddr || dr->section->bss)) + v.push_back(dr); + return v; } // Returns a map from sections to their symbols. -static SymbolMapTy getSectionSyms(ArrayRef Syms) { - SymbolMapTy Ret; - for (Defined *DR : Syms) - Ret[DR->Section].push_back(DR); +static SymbolMapTy getSectionSyms(ArrayRef syms) { + SymbolMapTy ret; + for (Defined *dr : syms) + ret[dr->section].push_back(dr); // Sort symbols by address. We want to print out symbols in the // order in the output file rather than the order they appeared // in the input files. - for (auto &It : Ret) - llvm::stable_sort(It.second, [](Defined *A, Defined *B) { - return A->getVA() < B->getVA(); + for (auto &it : ret) + llvm::stable_sort(it.second, [](Defined *a, Defined *b) { + return a->getVA() < b->getVA(); }); - return Ret; + return ret; } // Construct a map from symbols to their stringified representations. // Demangling symbols (which is what toString() does) is slow, so // we do that in batch using parallel-for. static DenseMap -getSymbolStrings(ArrayRef Syms) { - std::vector Str(Syms.size()); - parallelForEachN(0, Syms.size(), [&](size_t I) { - raw_string_ostream OS(Str[I]); - OutputSection *OSec = Syms[I]->getOutputSection(); - uint64_t VMA = Syms[I]->getVA(); - uint64_t LMA = OSec ? OSec->getLMA() + VMA - OSec->getVA(0) : 0; - writeHeader(OS, VMA, LMA, Syms[I]->getSize(), 1); - OS << Indent16 << toString(*Syms[I]); +getSymbolStrings(ArrayRef syms) { + std::vector str(syms.size()); + parallelForEachN(0, syms.size(), [&](size_t i) { + raw_string_ostream os(str[i]); + OutputSection *osec = syms[i]->getOutputSection(); + uint64_t vma = syms[i]->getVA(); + uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0; + writeHeader(os, vma, lma, syms[i]->getSize(), 1); + os << indent16 << toString(*syms[i]); }); - DenseMap Ret; - for (size_t I = 0, E = Syms.size(); I < E; ++I) - Ret[Syms[I]] = std::move(Str[I]); - return Ret; + DenseMap ret; + for (size_t i = 0, e = syms.size(); i < e; ++i) + ret[syms[i]] = std::move(str[i]); + return ret; } // Print .eh_frame contents. Since the section consists of EhSectionPieces, @@ -106,115 +106,115 @@ // .eh_frame tend to contain a lot of section pieces that are contiguous // both in input file and output file. Such pieces are squashed before // being displayed to make output compact. -static void printEhFrame(raw_ostream &OS, const EhFrameSection *Sec) { - std::vector Pieces; +static void printEhFrame(raw_ostream &os, const EhFrameSection *sec) { + std::vector pieces; - auto Add = [&](const EhSectionPiece &P) { + auto add = [&](const EhSectionPiece &p) { // If P is adjacent to Last, squash the two. - if (!Pieces.empty()) { - EhSectionPiece &Last = Pieces.back(); - if (Last.Sec == P.Sec && Last.InputOff + Last.Size == P.InputOff && - Last.OutputOff + Last.Size == P.OutputOff) { - Last.Size += P.Size; + if (!pieces.empty()) { + EhSectionPiece &last = pieces.back(); + if (last.sec == p.sec && last.inputOff + last.size == p.inputOff && + last.outputOff + last.size == p.outputOff) { + last.size += p.size; return; } } - Pieces.push_back(P); + pieces.push_back(p); }; // Gather section pieces. - for (const CieRecord *Rec : Sec->getCieRecords()) { - Add(*Rec->Cie); - for (const EhSectionPiece *Fde : Rec->Fdes) - Add(*Fde); + for (const CieRecord *rec : sec->getCieRecords()) { + add(*rec->cie); + for (const EhSectionPiece *fde : rec->fdes) + add(*fde); } // Print out section pieces. - const OutputSection *OSec = Sec->getOutputSection(); - for (EhSectionPiece &P : Pieces) { - writeHeader(OS, OSec->Addr + P.OutputOff, OSec->getLMA() + P.OutputOff, - P.Size, 1); - OS << Indent8 << toString(P.Sec->File) << ":(" << P.Sec->Name << "+0x" - << Twine::utohexstr(P.InputOff) + ")\n"; + const OutputSection *osec = sec->getOutputSection(); + for (EhSectionPiece &p : pieces) { + writeHeader(os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff, + p.size, 1); + os << indent8 << toString(p.sec->file) << ":(" << p.sec->name << "+0x" + << Twine::utohexstr(p.inputOff) + ")\n"; } } void elf::writeMapFile() { - if (Config->MapFile.empty()) + if (config->mapFile.empty()) return; // Open a map file for writing. - std::error_code EC; - raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); - if (EC) { - error("cannot open " + Config->MapFile + ": " + EC.message()); + std::error_code ec; + raw_fd_ostream os(config->mapFile, ec, sys::fs::F_None); + if (ec) { + error("cannot open " + config->mapFile + ": " + ec.message()); return; } // Collect symbol info that we want to print out. - std::vector Syms = getSymbols(); - SymbolMapTy SectionSyms = getSectionSyms(Syms); - DenseMap SymStr = getSymbolStrings(Syms); + std::vector syms = getSymbols(); + SymbolMapTy sectionSyms = getSectionSyms(syms); + DenseMap symStr = getSymbolStrings(syms); // Print out the header line. - int W = Config->Is64 ? 16 : 8; - OS << right_justify("VMA", W) << ' ' << right_justify("LMA", W) + int w = config->is64 ? 16 : 8; + os << right_justify("VMA", w) << ' ' << right_justify("LMA", w) << " Size Align Out In Symbol\n"; - OutputSection* OSec = nullptr; - for (BaseCommand *Base : Script->SectionCommands) { - if (auto *Cmd = dyn_cast(Base)) { - if (Cmd->Provide && !Cmd->Sym) + OutputSection* osec = nullptr; + for (BaseCommand *base : script->sectionCommands) { + if (auto *cmd = dyn_cast(base)) { + if (cmd->provide && !cmd->sym) continue; - uint64_t LMA = OSec ? OSec->getLMA() + Cmd->Addr - OSec->getVA(0) : 0; - writeHeader(OS, Cmd->Addr, LMA, Cmd->Size, 1); - OS << Cmd->CommandString << '\n'; + uint64_t lma = osec ? osec->getLMA() + cmd->addr - osec->getVA(0) : 0; + writeHeader(os, cmd->addr, lma, cmd->size, 1); + os << cmd->commandString << '\n'; continue; } - OSec = cast(Base); - writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment); - OS << OSec->Name << '\n'; + osec = cast(base); + writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment); + os << osec->name << '\n'; // Dump symbols for each input section. - for (BaseCommand *Base : OSec->SectionCommands) { - if (auto *ISD = dyn_cast(Base)) { - for (InputSection *IS : ISD->Sections) { - if (auto *EhSec = dyn_cast(IS)) { - printEhFrame(OS, EhSec); + for (BaseCommand *base : osec->sectionCommands) { + if (auto *isd = dyn_cast(base)) { + for (InputSection *isec : isd->sections) { + if (auto *ehSec = dyn_cast(isec)) { + printEhFrame(os, ehSec); continue; } - writeHeader(OS, IS->getVA(0), OSec->getLMA() + IS->getOffset(0), - IS->getSize(), IS->Alignment); - OS << Indent8 << toString(IS) << '\n'; - for (Symbol *Sym : SectionSyms[IS]) - OS << SymStr[Sym] << '\n'; + writeHeader(os, isec->getVA(0), osec->getLMA() + isec->getOffset(0), + isec->getSize(), isec->alignment); + os << indent8 << toString(isec) << '\n'; + for (Symbol *sym : sectionSyms[isec]) + os << symStr[sym] << '\n'; } continue; } - if (auto *Cmd = dyn_cast(Base)) { - writeHeader(OS, OSec->Addr + Cmd->Offset, OSec->getLMA() + Cmd->Offset, - Cmd->Size, 1); - OS << Indent8 << Cmd->CommandString << '\n'; + if (auto *cmd = dyn_cast(base)) { + writeHeader(os, osec->addr + cmd->offset, osec->getLMA() + cmd->offset, + cmd->size, 1); + os << indent8 << cmd->commandString << '\n'; continue; } - if (auto *Cmd = dyn_cast(Base)) { - if (Cmd->Provide && !Cmd->Sym) + if (auto *cmd = dyn_cast(base)) { + if (cmd->provide && !cmd->sym) continue; - writeHeader(OS, Cmd->Addr, OSec->getLMA() + Cmd->Addr - OSec->getVA(0), - Cmd->Size, 1); - OS << Indent8 << Cmd->CommandString << '\n'; + writeHeader(os, cmd->addr, osec->getLMA() + cmd->addr - osec->getVA(0), + cmd->size, 1); + os << indent8 << cmd->commandString << '\n'; continue; } } } } -static void print(StringRef A, StringRef B) { - outs() << left_justify(A, 49) << " " << B << "\n"; +static void print(StringRef a, StringRef b) { + outs() << left_justify(a, 49) << " " << b << "\n"; } // Output a cross reference table to stdout. This is for --cref. @@ -229,18 +229,18 @@ // In this case, strlen is defined by libc.so.6 and used by other two // files. void elf::writeCrossReferenceTable() { - if (!Config->Cref) + if (!config->cref) return; // Collect symbols and files. - MapVector> Map; - for (InputFile *File : ObjectFiles) { - for (Symbol *Sym : File->getSymbols()) { - if (isa(Sym)) - Map[Sym].insert(File); - if (auto *D = dyn_cast(Sym)) - if (!D->isLocal() && (!D->Section || D->Section->isLive())) - Map[D].insert(File); + MapVector> map; + for (InputFile *file : objectFiles) { + for (Symbol *sym : file->getSymbols()) { + if (isa(sym)) + map[sym].insert(file); + if (auto *d = dyn_cast(sym)) + if (!d->isLocal() && (!d->section || d->section->isLive())) + map[d].insert(file); } } @@ -249,13 +249,13 @@ print("Symbol", "File"); // Print out a table. - for (auto KV : Map) { - Symbol *Sym = KV.first; - SetVector &Files = KV.second; - - print(toString(*Sym), toString(Sym->File)); - for (InputFile *File : Files) - if (File != Sym->File) - print("", toString(File)); + for (auto kv : map) { + Symbol *sym = kv.first; + SetVector &files = kv.second; + + print(toString(*sym), toString(sym->file)); + for (InputFile *file : files) + if (file != sym->file) + print("", toString(file)); } } Index: lld/trunk/ELF/MarkLive.cpp =================================================================== --- lld/trunk/ELF/MarkLive.cpp +++ lld/trunk/ELF/MarkLive.cpp @@ -45,76 +45,76 @@ namespace { template class MarkLive { public: - MarkLive(unsigned Partition) : Partition(Partition) {} + MarkLive(unsigned partition) : partition(partition) {} void run(); void moveToMain(); private: - void enqueue(InputSectionBase *Sec, uint64_t Offset); - void markSymbol(Symbol *Sym); + void enqueue(InputSectionBase *sec, uint64_t offset); + void markSymbol(Symbol *sym); void mark(); template - void resolveReloc(InputSectionBase &Sec, RelTy &Rel, bool IsLSDA); + void resolveReloc(InputSectionBase &sec, RelTy &rel, bool isLSDA); template - void scanEhFrameSection(EhInputSection &EH, ArrayRef Rels); + void scanEhFrameSection(EhInputSection &eh, ArrayRef rels); // The index of the partition that we are currently processing. - unsigned Partition; + unsigned partition; // A list of sections to visit. - SmallVector Queue; + SmallVector queue; // There are normally few input sections whose names are valid C // identifiers, so we just store a std::vector instead of a multimap. - DenseMap> CNamedSections; + DenseMap> cNamedSections; }; } // namespace template -static uint64_t getAddend(InputSectionBase &Sec, - const typename ELFT::Rel &Rel) { - return Target->getImplicitAddend(Sec.data().begin() + Rel.r_offset, - Rel.getType(Config->IsMips64EL)); +static uint64_t getAddend(InputSectionBase &sec, + const typename ELFT::Rel &rel) { + return target->getImplicitAddend(sec.data().begin() + rel.r_offset, + rel.getType(config->isMips64EL)); } template -static uint64_t getAddend(InputSectionBase &Sec, - const typename ELFT::Rela &Rel) { - return Rel.r_addend; +static uint64_t getAddend(InputSectionBase &sec, + const typename ELFT::Rela &rel) { + return rel.r_addend; } template template -void MarkLive::resolveReloc(InputSectionBase &Sec, RelTy &Rel, - bool IsLSDA) { - Symbol &Sym = Sec.getFile()->getRelocTargetSym(Rel); +void MarkLive::resolveReloc(InputSectionBase &sec, RelTy &rel, + bool isLSDA) { + Symbol &sym = sec.getFile()->getRelocTargetSym(rel); // If a symbol is referenced in a live section, it is used. - Sym.Used = true; + sym.used = true; - if (auto *D = dyn_cast(&Sym)) { - auto *RelSec = dyn_cast_or_null(D->Section); - if (!RelSec) + if (auto *d = dyn_cast(&sym)) { + auto *relSec = dyn_cast_or_null(d->section); + if (!relSec) return; - uint64_t Offset = D->Value; - if (D->isSection()) - Offset += getAddend(Sec, Rel); + uint64_t offset = d->value; + if (d->isSection()) + offset += getAddend(sec, rel); - if (!IsLSDA || !(RelSec->Flags & SHF_EXECINSTR)) - enqueue(RelSec, Offset); + if (!isLSDA || !(relSec->flags & SHF_EXECINSTR)) + enqueue(relSec, offset); return; } - if (auto *SS = dyn_cast(&Sym)) - if (!SS->isWeak()) - SS->getFile().IsNeeded = true; + if (auto *ss = dyn_cast(&sym)) + if (!ss->isWeak()) + ss->getFile().isNeeded = true; - for (InputSectionBase *Sec : CNamedSections.lookup(Sym.getName())) - enqueue(Sec, 0); + for (InputSectionBase *sec : cNamedSections.lookup(sym.getName())) + enqueue(sec, 0); } // The .eh_frame section is an unfortunate special case. @@ -133,80 +133,80 @@ // LSDAs and personality functions if we found that they were unused. template template -void MarkLive::scanEhFrameSection(EhInputSection &EH, - ArrayRef Rels) { - for (size_t I = 0, End = EH.Pieces.size(); I < End; ++I) { - EhSectionPiece &Piece = EH.Pieces[I]; - size_t FirstRelI = Piece.FirstRelocation; - if (FirstRelI == (unsigned)-1) +void MarkLive::scanEhFrameSection(EhInputSection &eh, + ArrayRef rels) { + for (size_t i = 0, end = eh.pieces.size(); i < end; ++i) { + EhSectionPiece &piece = eh.pieces[i]; + size_t firstRelI = piece.firstRelocation; + if (firstRelI == (unsigned)-1) continue; - if (read32(Piece.data().data() + 4) == 0) { + if (read32(piece.data().data() + 4) == 0) { // This is a CIE, we only need to worry about the first relocation. It is // known to point to the personality function. - resolveReloc(EH, Rels[FirstRelI], false); + resolveReloc(eh, rels[firstRelI], false); continue; } // This is a FDE. The relocations point to the described function or to // a LSDA. We only need to keep the LSDA alive, so ignore anything that // points to executable sections. - uint64_t PieceEnd = Piece.InputOff + Piece.Size; - for (size_t J = FirstRelI, End2 = Rels.size(); J < End2; ++J) - if (Rels[J].r_offset < PieceEnd) - resolveReloc(EH, Rels[J], true); + uint64_t pieceEnd = piece.inputOff + piece.size; + for (size_t j = firstRelI, end2 = rels.size(); j < end2; ++j) + if (rels[j].r_offset < pieceEnd) + resolveReloc(eh, rels[j], true); } } // Some sections are used directly by the loader, so they should never be // garbage-collected. This function returns true if a given section is such // section. -static bool isReserved(InputSectionBase *Sec) { - switch (Sec->Type) { +static bool isReserved(InputSectionBase *sec) { + switch (sec->type) { case SHT_FINI_ARRAY: case SHT_INIT_ARRAY: case SHT_NOTE: case SHT_PREINIT_ARRAY: return true; default: - StringRef S = Sec->Name; - return S.startswith(".ctors") || S.startswith(".dtors") || - S.startswith(".init") || S.startswith(".fini") || - S.startswith(".jcr"); + StringRef s = sec->name; + return s.startswith(".ctors") || s.startswith(".dtors") || + s.startswith(".init") || s.startswith(".fini") || + s.startswith(".jcr"); } } template -void MarkLive::enqueue(InputSectionBase *Sec, uint64_t Offset) { +void MarkLive::enqueue(InputSectionBase *sec, uint64_t offset) { // Skip over discarded sections. This in theory shouldn't happen, because // the ELF spec doesn't allow a relocation to point to a deduplicated // COMDAT section directly. Unfortunately this happens in practice (e.g. // .eh_frame) so we need to add a check. - if (Sec == &InputSection::Discarded) + if (sec == &InputSection::discarded) return; // Usually, a whole section is marked as live or dead, but in mergeable // (splittable) sections, each piece of data has independent liveness bit. // So we explicitly tell it which offset is in use. - if (auto *MS = dyn_cast(Sec)) - MS->getSectionPiece(Offset)->Live = true; + if (auto *ms = dyn_cast(sec)) + ms->getSectionPiece(offset)->live = true; // Set Sec->Partition to the meet (i.e. the "minimum") of Partition and // Sec->Partition in the following lattice: 1 < other < 0. If Sec->Partition // doesn't change, we don't need to do anything. - if (Sec->Partition == 1 || Sec->Partition == Partition) + if (sec->partition == 1 || sec->partition == partition) return; - Sec->Partition = Sec->Partition ? 1 : Partition; + sec->partition = sec->partition ? 1 : partition; // Add input section to the queue. - if (InputSection *S = dyn_cast(Sec)) - Queue.push_back(S); + if (InputSection *s = dyn_cast(sec)) + queue.push_back(s); } -template void MarkLive::markSymbol(Symbol *Sym) { - if (auto *D = dyn_cast_or_null(Sym)) - if (auto *IS = dyn_cast_or_null(D->Section)) - enqueue(IS, D->Value); +template void MarkLive::markSymbol(Symbol *sym) { + if (auto *d = dyn_cast_or_null(sym)) + if (auto *isec = dyn_cast_or_null(d->section)) + enqueue(isec, d->value); } // This is the main function of the garbage collector. @@ -217,51 +217,51 @@ // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. - Symtab->forEachSymbol([&](Symbol *Sym) { - if (Sym->includeInDynsym() && Sym->Partition == Partition) - markSymbol(Sym); + symtab->forEachSymbol([&](Symbol *sym) { + if (sym->includeInDynsym() && sym->partition == partition) + markSymbol(sym); }); // If this isn't the main partition, that's all that we need to preserve. - if (Partition != 1) { + if (partition != 1) { mark(); return; } - markSymbol(Symtab->find(Config->Entry)); - markSymbol(Symtab->find(Config->Init)); - markSymbol(Symtab->find(Config->Fini)); - for (StringRef S : Config->Undefined) - markSymbol(Symtab->find(S)); - for (StringRef S : Script->ReferencedSymbols) - markSymbol(Symtab->find(S)); + markSymbol(symtab->find(config->entry)); + markSymbol(symtab->find(config->init)); + markSymbol(symtab->find(config->fini)); + for (StringRef s : config->undefined) + markSymbol(symtab->find(s)); + for (StringRef s : script->referencedSymbols) + markSymbol(symtab->find(s)); // Preserve special sections and those which are specified in linker // script KEEP command. - for (InputSectionBase *Sec : InputSections) { + for (InputSectionBase *sec : inputSections) { // Mark .eh_frame sections as live because there are usually no relocations // that point to .eh_frames. Otherwise, the garbage collector would drop // all of them. We also want to preserve personality routines and LSDA // referenced by .eh_frame sections, so we scan them for that here. - if (auto *EH = dyn_cast(Sec)) { - EH->markLive(); - if (!EH->NumRelocations) + if (auto *eh = dyn_cast(sec)) { + eh->markLive(); + if (!eh->numRelocations) continue; - if (EH->AreRelocsRela) - scanEhFrameSection(*EH, EH->template relas()); + if (eh->areRelocsRela) + scanEhFrameSection(*eh, eh->template relas()); else - scanEhFrameSection(*EH, EH->template rels()); + scanEhFrameSection(*eh, eh->template rels()); } - if (Sec->Flags & SHF_LINK_ORDER) + if (sec->flags & SHF_LINK_ORDER) continue; - if (isReserved(Sec) || Script->shouldKeep(Sec)) { - enqueue(Sec, 0); - } else if (isValidCIdentifier(Sec->Name)) { - CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); - CNamedSections[Saver.save("__stop_" + Sec->Name)].push_back(Sec); + if (isReserved(sec) || script->shouldKeep(sec)) { + enqueue(sec, 0); + } else if (isValidCIdentifier(sec->name)) { + cNamedSections[Saver.save("__start_" + sec->name)].push_back(sec); + cNamedSections[Saver.save("__stop_" + sec->name)].push_back(sec); } } @@ -270,19 +270,19 @@ template void MarkLive::mark() { // Mark all reachable sections. - while (!Queue.empty()) { - InputSectionBase &Sec = *Queue.pop_back_val(); + while (!queue.empty()) { + InputSectionBase &sec = *queue.pop_back_val(); - if (Sec.AreRelocsRela) { - for (const typename ELFT::Rela &Rel : Sec.template relas()) - resolveReloc(Sec, Rel, false); + if (sec.areRelocsRela) { + for (const typename ELFT::Rela &rel : sec.template relas()) + resolveReloc(sec, rel, false); } else { - for (const typename ELFT::Rel &Rel : Sec.template rels()) - resolveReloc(Sec, Rel, false); + for (const typename ELFT::Rel &rel : sec.template rels()) + resolveReloc(sec, rel, false); } - for (InputSectionBase *IS : Sec.DependentSections) - enqueue(IS, 0); + for (InputSectionBase *isec : sec.dependentSections) + enqueue(isec, 0); } } @@ -292,12 +292,12 @@ // loaded) and TLS symbols (because we only know how to correctly process TLS // relocations for the main partition). template void MarkLive::moveToMain() { - for (InputFile *File : ObjectFiles) - for (Symbol *S : File->getSymbols()) - if (auto *D = dyn_cast(S)) - if ((D->Type == STT_GNU_IFUNC || D->Type == STT_TLS) && D->Section && - D->Section->isLive()) - markSymbol(S); + for (InputFile *file : objectFiles) + for (Symbol *s : file->getSymbols()) + if (auto *d = dyn_cast(s)) + if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && + d->section->isLive()) + markSymbol(s); mark(); } @@ -307,15 +307,15 @@ // so that they are emitted to the output file. template void elf::markLive() { // If -gc-sections is not given, no sections are removed. - if (!Config->GcSections) { - for (InputSectionBase *Sec : InputSections) - Sec->markLive(); + if (!config->gcSections) { + for (InputSectionBase *sec : inputSections) + sec->markLive(); // If a DSO defines a symbol referenced in a regular object, it is needed. - Symtab->forEachSymbol([](Symbol *Sym) { - if (auto *S = dyn_cast(Sym)) - if (S->IsUsedInRegularObj && !S->isWeak()) - S->getFile().IsNeeded = true; + symtab->forEachSymbol([](Symbol *sym) { + if (auto *s = dyn_cast(sym)) + if (s->isUsedInRegularObj && !s->isWeak()) + s->getFile().isNeeded = true; }); return; } @@ -341,30 +341,30 @@ // or -emit-reloc were given. And they are subject of garbage // collection because, if we remove a text section, we also // remove its relocation section. - for (InputSectionBase *Sec : InputSections) { - bool IsAlloc = (Sec->Flags & SHF_ALLOC); - bool IsLinkOrder = (Sec->Flags & SHF_LINK_ORDER); - bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA); + for (InputSectionBase *sec : inputSections) { + bool isAlloc = (sec->flags & SHF_ALLOC); + bool isLinkOrder = (sec->flags & SHF_LINK_ORDER); + bool isRel = (sec->type == SHT_REL || sec->type == SHT_RELA); - if (!IsAlloc && !IsLinkOrder && !IsRel) - Sec->markLive(); + if (!isAlloc && !isLinkOrder && !isRel) + sec->markLive(); } // Follow the graph to mark all live sections. - for (unsigned CurPart = 1; CurPart <= Partitions.size(); ++CurPart) - MarkLive(CurPart).run(); + for (unsigned curPart = 1; curPart <= partitions.size(); ++curPart) + MarkLive(curPart).run(); // If we have multiple partitions, some sections need to live in the main // partition even if they were allocated to a loadable partition. Move them // there now. - if (Partitions.size() != 1) + if (partitions.size() != 1) MarkLive(1).moveToMain(); // Report garbage-collected sections. - if (Config->PrintGcSections) - for (InputSectionBase *Sec : InputSections) - if (!Sec->isLive()) - message("removing unused section " + toString(Sec)); + if (config->printGcSections) + for (InputSectionBase *sec : inputSections) + if (!sec->isLive()) + message("removing unused section " + toString(sec)); } template void elf::markLive(); Index: lld/trunk/ELF/OutputSections.h =================================================================== --- lld/trunk/ELF/OutputSections.h +++ lld/trunk/ELF/OutputSections.h @@ -31,19 +31,19 @@ // non-overlapping file offsets and VAs. class OutputSection final : public BaseCommand, public SectionBase { public: - OutputSection(StringRef Name, uint32_t Type, uint64_t Flags); + OutputSection(StringRef name, uint32_t type, uint64_t flags); - static bool classof(const SectionBase *S) { - return S->kind() == SectionBase::Output; + static bool classof(const SectionBase *s) { + return s->kind() == SectionBase::Output; } - static bool classof(const BaseCommand *C); + static bool classof(const BaseCommand *c); - uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; } - template void writeHeaderTo(typename ELFT::Shdr *SHdr); + uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; } + template void writeHeaderTo(typename ELFT::Shdr *sHdr); - uint32_t SectionIndex = UINT32_MAX; - unsigned SortRank; + uint32_t sectionIndex = UINT32_MAX; + unsigned sortRank; uint32_t getPhdrFlags() const; @@ -54,82 +54,82 @@ // section offset we use the following formula: Off = Off_first + VA - // VA_first, where Off_first and VA_first is file offset and VA of first // section in PT_LOAD. - PhdrEntry *PtLoad = nullptr; + PhdrEntry *ptLoad = nullptr; // Pointer to a relocation section for this section. Usually nullptr because // we consume relocations, but if --emit-relocs is specified (which is rare), // it may have a non-null value. - OutputSection *RelocationSection = nullptr; + OutputSection *relocationSection = nullptr; // Initially this field is the number of InputSections that have been added to // the OutputSection so far. Later on, after a call to assignAddresses, it // corresponds to the Elf_Shdr member. - uint64_t Size = 0; + uint64_t size = 0; // The following fields correspond to Elf_Shdr members. - uint64_t Offset = 0; - uint64_t Addr = 0; - uint32_t ShName = 0; + uint64_t offset = 0; + uint64_t addr = 0; + uint32_t shName = 0; - void addSection(InputSection *IS); + void addSection(InputSection *isec); // The following members are normally only used in linker scripts. - MemoryRegion *MemRegion = nullptr; - MemoryRegion *LMARegion = nullptr; - Expr AddrExpr; - Expr AlignExpr; - Expr LMAExpr; - Expr SubalignExpr; - std::vector SectionCommands; - std::vector Phdrs; - llvm::Optional> Filler; - ConstraintKind Constraint = ConstraintKind::NoConstraint; - std::string Location; - std::string MemoryRegionName; - std::string LMARegionName; - bool NonAlloc = false; - bool Noload = false; - bool ExpressionsUseSymbols = false; - bool UsedInExpression = false; - bool InOverlay = false; + MemoryRegion *memRegion = nullptr; + MemoryRegion *lmaRegion = nullptr; + Expr addrExpr; + Expr alignExpr; + Expr lmaExpr; + Expr subalignExpr; + std::vector sectionCommands; + std::vector phdrs; + llvm::Optional> filler; + ConstraintKind constraint = ConstraintKind::NoConstraint; + std::string location; + std::string memoryRegionName; + std::string lmaRegionName; + bool nonAlloc = false; + bool noload = false; + bool expressionsUseSymbols = false; + bool usedInExpression = false; + bool inOverlay = false; // Tracks whether the section has ever had an input section added to it, even // if the section was later removed (e.g. because it is a synthetic section // that wasn't needed). This is needed for orphan placement. - bool HasInputSections = false; + bool hasInputSections = false; void finalize(); - template void writeTo(uint8_t *Buf); + template void writeTo(uint8_t *buf); template void maybeCompress(); - void sort(llvm::function_ref Order); + void sort(llvm::function_ref order); void sortInitFini(); void sortCtorsDtors(); private: // Used for implementation of --compress-debug-sections option. - std::vector ZDebugHeader; - llvm::SmallVector CompressedData; + std::vector zDebugHeader; + llvm::SmallVector compressedData; std::array getFiller(); }; -int getPriority(StringRef S); +int getPriority(StringRef s); -std::vector getInputSections(OutputSection* OS); +std::vector getInputSections(OutputSection* os); // All output sections that are handled by the linker specially are // globally accessible. Writer initializes them, so don't use them // until Writer is initialized. struct Out { - static uint8_t *BufferStart; - static uint8_t First; - static PhdrEntry *TlsPhdr; - static OutputSection *ElfHeader; - static OutputSection *ProgramHeaders; - static OutputSection *PreinitArray; - static OutputSection *InitArray; - static OutputSection *FiniArray; + static uint8_t *bufferStart; + static uint8_t first; + static PhdrEntry *tlsPhdr; + static OutputSection *elfHeader; + static OutputSection *programHeaders; + static OutputSection *preinitArray; + static OutputSection *initArray; + static OutputSection *finiArray; }; } // namespace elf @@ -140,7 +140,7 @@ uint64_t getHeaderSize(); -extern std::vector OutputSections; +extern std::vector outputSections; } // namespace elf } // namespace lld Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -30,45 +30,45 @@ using namespace lld; using namespace lld::elf; -uint8_t *Out::BufferStart; -uint8_t Out::First; -PhdrEntry *Out::TlsPhdr; -OutputSection *Out::ElfHeader; -OutputSection *Out::ProgramHeaders; -OutputSection *Out::PreinitArray; -OutputSection *Out::InitArray; -OutputSection *Out::FiniArray; +uint8_t *Out::bufferStart; +uint8_t Out::first; +PhdrEntry *Out::tlsPhdr; +OutputSection *Out::elfHeader; +OutputSection *Out::programHeaders; +OutputSection *Out::preinitArray; +OutputSection *Out::initArray; +OutputSection *Out::finiArray; -std::vector elf::OutputSections; +std::vector elf::outputSections; uint32_t OutputSection::getPhdrFlags() const { - uint32_t Ret = 0; - if (Config->EMachine != EM_ARM || !(Flags & SHF_ARM_PURECODE)) - Ret |= PF_R; - if (Flags & SHF_WRITE) - Ret |= PF_W; - if (Flags & SHF_EXECINSTR) - Ret |= PF_X; - return Ret; + uint32_t ret = 0; + if (config->emachine != EM_ARM || !(flags & SHF_ARM_PURECODE)) + ret |= PF_R; + if (flags & SHF_WRITE) + ret |= PF_W; + if (flags & SHF_EXECINSTR) + ret |= PF_X; + return ret; } template -void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) { - Shdr->sh_entsize = Entsize; - Shdr->sh_addralign = Alignment; - Shdr->sh_type = Type; - Shdr->sh_offset = Offset; - Shdr->sh_flags = Flags; - Shdr->sh_info = Info; - Shdr->sh_link = Link; - Shdr->sh_addr = Addr; - Shdr->sh_size = Size; - Shdr->sh_name = ShName; +void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) { + shdr->sh_entsize = entsize; + shdr->sh_addralign = alignment; + shdr->sh_type = type; + shdr->sh_offset = offset; + shdr->sh_flags = flags; + shdr->sh_info = info; + shdr->sh_link = link; + shdr->sh_addr = addr; + shdr->sh_size = size; + shdr->sh_name = shName; } -OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags) +OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags) : BaseCommand(OutputSectionKind), - SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type, + SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type, /*Info*/ 0, /*Link*/ 0) {} // We allow sections of types listed below to merged into a @@ -77,102 +77,102 @@ // to be allocated for nobits sections. Other ones don't require // any special treatment on top of progbits, so there doesn't // seem to be a harm in merging them. -static bool canMergeToProgbits(unsigned Type) { - return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY || - Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY || - Type == SHT_NOTE; +static bool canMergeToProgbits(unsigned type) { + return type == SHT_NOBITS || type == SHT_PROGBITS || type == SHT_INIT_ARRAY || + type == SHT_PREINIT_ARRAY || type == SHT_FINI_ARRAY || + type == SHT_NOTE; } -void OutputSection::addSection(InputSection *IS) { - if (!HasInputSections) { +void OutputSection::addSection(InputSection *isec) { + if (!hasInputSections) { // If IS is the first section to be added to this section, // initialize Partition, Type, Entsize and flags from IS. - HasInputSections = true; - Partition = IS->Partition; - Type = IS->Type; - Entsize = IS->Entsize; - Flags = IS->Flags; + hasInputSections = true; + partition = isec->partition; + type = isec->type; + entsize = isec->entsize; + flags = isec->flags; } else { // Otherwise, check if new type or flags are compatible with existing ones. - unsigned Mask = SHF_TLS | SHF_LINK_ORDER; - if ((Flags & Mask) != (IS->Flags & Mask)) - error("incompatible section flags for " + Name + "\n>>> " + toString(IS) + - ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name + - ": 0x" + utohexstr(Flags)); - - if (Type != IS->Type) { - if (!canMergeToProgbits(Type) || !canMergeToProgbits(IS->Type)) - error("section type mismatch for " + IS->Name + "\n>>> " + - toString(IS) + ": " + - getELFSectionTypeName(Config->EMachine, IS->Type) + - "\n>>> output section " + Name + ": " + - getELFSectionTypeName(Config->EMachine, Type)); - Type = SHT_PROGBITS; + unsigned mask = SHF_TLS | SHF_LINK_ORDER; + if ((flags & mask) != (isec->flags & mask)) + error("incompatible section flags for " + name + "\n>>> " + toString(isec) + + ": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name + + ": 0x" + utohexstr(flags)); + + if (type != isec->type) { + if (!canMergeToProgbits(type) || !canMergeToProgbits(isec->type)) + error("section type mismatch for " + isec->name + "\n>>> " + + toString(isec) + ": " + + getELFSectionTypeName(config->emachine, isec->type) + + "\n>>> output section " + name + ": " + + getELFSectionTypeName(config->emachine, type)); + type = SHT_PROGBITS; } } - IS->Parent = this; - uint64_t AndMask = - Config->EMachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0; - uint64_t OrMask = ~AndMask; - uint64_t AndFlags = (Flags & IS->Flags) & AndMask; - uint64_t OrFlags = (Flags | IS->Flags) & OrMask; - Flags = AndFlags | OrFlags; + isec->parent = this; + uint64_t andMask = + config->emachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0; + uint64_t orMask = ~andMask; + uint64_t andFlags = (flags & isec->flags) & andMask; + uint64_t orFlags = (flags | isec->flags) & orMask; + flags = andFlags | orFlags; - Alignment = std::max(Alignment, IS->Alignment); + alignment = std::max(alignment, isec->alignment); // If this section contains a table of fixed-size entries, sh_entsize // holds the element size. If it contains elements of different size we // set sh_entsize to 0. - if (Entsize != IS->Entsize) - Entsize = 0; + if (entsize != isec->entsize) + entsize = 0; - if (!IS->Assigned) { - IS->Assigned = true; - if (SectionCommands.empty() || - !isa(SectionCommands.back())) - SectionCommands.push_back(make("")); - auto *ISD = cast(SectionCommands.back()); - ISD->Sections.push_back(IS); + if (!isec->assigned) { + isec->assigned = true; + if (sectionCommands.empty() || + !isa(sectionCommands.back())) + sectionCommands.push_back(make("")); + auto *isd = cast(sectionCommands.back()); + isd->sections.push_back(isec); } } -static void sortByOrder(MutableArrayRef In, - llvm::function_ref Order) { - std::vector> V; - for (InputSection *S : In) - V.push_back({Order(S), S}); - llvm::stable_sort(V, less_first()); +static void sortByOrder(MutableArrayRef in, + llvm::function_ref order) { + std::vector> v; + for (InputSection *s : in) + v.push_back({order(s), s}); + llvm::stable_sort(v, less_first()); - for (size_t I = 0; I < V.size(); ++I) - In[I] = V[I].second; + for (size_t i = 0; i < v.size(); ++i) + in[i] = v[i].second; } uint64_t elf::getHeaderSize() { - if (Config->OFormatBinary) + if (config->oFormatBinary) return 0; - return Out::ElfHeader->Size + Out::ProgramHeaders->Size; + return Out::elfHeader->size + Out::programHeaders->size; } -bool OutputSection::classof(const BaseCommand *C) { - return C->Kind == OutputSectionKind; +bool OutputSection::classof(const BaseCommand *c) { + return c->kind == OutputSectionKind; } -void OutputSection::sort(llvm::function_ref Order) { +void OutputSection::sort(llvm::function_ref order) { assert(isLive()); - for (BaseCommand *B : SectionCommands) - if (auto *ISD = dyn_cast(B)) - sortByOrder(ISD->Sections, Order); + for (BaseCommand *b : sectionCommands) + if (auto *isd = dyn_cast(b)) + sortByOrder(isd->sections, order); } // Fill [Buf, Buf + Size) with Filler. // This is used for linker script "=fillexp" command. -static void fill(uint8_t *Buf, size_t Size, - const std::array &Filler) { - size_t I = 0; - for (; I + 4 < Size; I += 4) - memcpy(Buf + I, Filler.data(), 4); - memcpy(Buf + I, Filler.data(), Size - I); +static void fill(uint8_t *buf, size_t size, + const std::array &filler) { + size_t i = 0; + for (; i + 4 < size; i += 4) + memcpy(buf + i, filler.data(), 4); + memcpy(buf + i, filler.data(), size - i); } // Compress section contents if this section contains debug info. @@ -180,145 +180,145 @@ using Elf_Chdr = typename ELFT::Chdr; // Compress only DWARF debug sections. - if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) || - !Name.startswith(".debug_")) + if (!config->compressDebugSections || (flags & SHF_ALLOC) || + !name.startswith(".debug_")) return; // Create a section header. - ZDebugHeader.resize(sizeof(Elf_Chdr)); - auto *Hdr = reinterpret_cast(ZDebugHeader.data()); - Hdr->ch_type = ELFCOMPRESS_ZLIB; - Hdr->ch_size = Size; - Hdr->ch_addralign = Alignment; + zDebugHeader.resize(sizeof(Elf_Chdr)); + auto *hdr = reinterpret_cast(zDebugHeader.data()); + hdr->ch_type = ELFCOMPRESS_ZLIB; + hdr->ch_size = size; + hdr->ch_addralign = alignment; // Write section contents to a temporary buffer and compress it. - std::vector Buf(Size); - writeTo(Buf.data()); - if (Error E = zlib::compress(toStringRef(Buf), CompressedData)) - fatal("compress failed: " + llvm::toString(std::move(E))); + std::vector buf(size); + writeTo(buf.data()); + if (Error e = zlib::compress(toStringRef(buf), compressedData)) + fatal("compress failed: " + llvm::toString(std::move(e))); // Update section headers. - Size = sizeof(Elf_Chdr) + CompressedData.size(); - Flags |= SHF_COMPRESSED; + size = sizeof(Elf_Chdr) + compressedData.size(); + flags |= SHF_COMPRESSED; } -static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { - if (Size == 1) - *Buf = Data; - else if (Size == 2) - write16(Buf, Data); - else if (Size == 4) - write32(Buf, Data); - else if (Size == 8) - write64(Buf, Data); +static void writeInt(uint8_t *buf, uint64_t data, uint64_t size) { + if (size == 1) + *buf = data; + else if (size == 2) + write16(buf, data); + else if (size == 4) + write32(buf, data); + else if (size == 8) + write64(buf, data); else llvm_unreachable("unsupported Size argument"); } -template void OutputSection::writeTo(uint8_t *Buf) { - if (Type == SHT_NOBITS) +template void OutputSection::writeTo(uint8_t *buf) { + if (type == SHT_NOBITS) return; // If -compress-debug-section is specified and if this is a debug seciton, // we've already compressed section contents. If that's the case, // just write it down. - if (!CompressedData.empty()) { - memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size()); - memcpy(Buf + ZDebugHeader.size(), CompressedData.data(), - CompressedData.size()); + if (!compressedData.empty()) { + memcpy(buf, zDebugHeader.data(), zDebugHeader.size()); + memcpy(buf + zDebugHeader.size(), compressedData.data(), + compressedData.size()); return; } // Write leading padding. - std::vector Sections = getInputSections(this); - std::array Filler = getFiller(); - bool NonZeroFiller = read32(Filler.data()) != 0; - if (NonZeroFiller) - fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler); - - parallelForEachN(0, Sections.size(), [&](size_t I) { - InputSection *IS = Sections[I]; - IS->writeTo(Buf); + std::vector sections = getInputSections(this); + std::array filler = getFiller(); + bool nonZeroFiller = read32(filler.data()) != 0; + if (nonZeroFiller) + fill(buf, sections.empty() ? size : sections[0]->outSecOff, filler); + + parallelForEachN(0, sections.size(), [&](size_t i) { + InputSection *isec = sections[i]; + isec->writeTo(buf); // Fill gaps between sections. - if (NonZeroFiller) { - uint8_t *Start = Buf + IS->OutSecOff + IS->getSize(); - uint8_t *End; - if (I + 1 == Sections.size()) - End = Buf + Size; + if (nonZeroFiller) { + uint8_t *start = buf + isec->outSecOff + isec->getSize(); + uint8_t *end; + if (i + 1 == sections.size()) + end = buf + size; else - End = Buf + Sections[I + 1]->OutSecOff; - fill(Start, End - Start, Filler); + end = buf + sections[i + 1]->outSecOff; + fill(start, end - start, filler); } }); // Linker scripts may have BYTE()-family commands with which you // can write arbitrary bytes to the output. Process them if any. - for (BaseCommand *Base : SectionCommands) - if (auto *Data = dyn_cast(Base)) - writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size); + for (BaseCommand *base : sectionCommands) + if (auto *data = dyn_cast(base)) + writeInt(buf + data->offset, data->expression().getValue(), data->size); } -static void finalizeShtGroup(OutputSection *OS, - InputSection *Section) { - assert(Config->Relocatable); +static void finalizeShtGroup(OutputSection *os, + InputSection *section) { + assert(config->relocatable); // sh_link field for SHT_GROUP sections should contain the section index of // the symbol table. - OS->Link = In.SymTab->getParent()->SectionIndex; + os->link = in.symTab->getParent()->sectionIndex; // sh_info then contain index of an entry in symbol table section which // provides signature of the section group. - ArrayRef Symbols = Section->File->getSymbols(); - OS->Info = In.SymTab->getSymbolIndex(Symbols[Section->Info]); + ArrayRef symbols = section->file->getSymbols(); + os->info = in.symTab->getSymbolIndex(symbols[section->info]); } void OutputSection::finalize() { - std::vector V = getInputSections(this); - InputSection *First = V.empty() ? nullptr : V[0]; + std::vector v = getInputSections(this); + InputSection *first = v.empty() ? nullptr : v[0]; - if (Flags & SHF_LINK_ORDER) { + if (flags & SHF_LINK_ORDER) { // We must preserve the link order dependency of sections with the // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, // all InputSections in the OutputSection have the same dependency. - if (auto *EX = dyn_cast(First)) - Link = EX->getLinkOrderDep()->getParent()->SectionIndex; - else if (auto *D = First->getLinkOrderDep()) - Link = D->getParent()->SectionIndex; + if (auto *ex = dyn_cast(first)) + link = ex->getLinkOrderDep()->getParent()->sectionIndex; + else if (auto *d = first->getLinkOrderDep()) + link = d->getParent()->sectionIndex; } - if (Type == SHT_GROUP) { - finalizeShtGroup(this, First); + if (type == SHT_GROUP) { + finalizeShtGroup(this, first); return; } - if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) + if (!config->copyRelocs || (type != SHT_RELA && type != SHT_REL)) return; - if (isa(First)) + if (isa(first)) return; - Link = In.SymTab->getParent()->SectionIndex; + link = in.symTab->getParent()->sectionIndex; // sh_info for SHT_REL[A] sections should contain the section header index of // the section to which the relocation applies. - InputSectionBase *S = First->getRelocatedSection(); - Info = S->getOutputSection()->SectionIndex; - Flags |= SHF_INFO_LINK; + InputSectionBase *s = first->getRelocatedSection(); + info = s->getOutputSection()->sectionIndex; + flags |= SHF_INFO_LINK; } // Returns true if S matches /Filename.?\.o$/. -static bool isCrtBeginEnd(StringRef S, StringRef Filename) { - if (!S.endswith(".o")) +static bool isCrtBeginEnd(StringRef s, StringRef filename) { + if (!s.endswith(".o")) return false; - S = S.drop_back(2); - if (S.endswith(Filename)) + s = s.drop_back(2); + if (s.endswith(filename)) return true; - return !S.empty() && S.drop_back().endswith(Filename); + return !s.empty() && s.drop_back().endswith(filename); } -static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); } -static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); } +static bool isCrtbegin(StringRef s) { return isCrtBeginEnd(s, "crtbegin"); } +static bool isCrtend(StringRef s) { return isCrtBeginEnd(s, "crtend"); } // .ctors and .dtors are sorted by this priority from highest to lowest. // @@ -338,52 +338,52 @@ // .ctors are duplicate features (and .init_array is newer.) However, there // are too many real-world use cases of .ctors, so we had no choice to // support that with this rather ad-hoc semantics. -static bool compCtors(const InputSection *A, const InputSection *B) { - bool BeginA = isCrtbegin(A->File->getName()); - bool BeginB = isCrtbegin(B->File->getName()); - if (BeginA != BeginB) - return BeginA; - bool EndA = isCrtend(A->File->getName()); - bool EndB = isCrtend(B->File->getName()); - if (EndA != EndB) - return EndB; - StringRef X = A->Name; - StringRef Y = B->Name; - assert(X.startswith(".ctors") || X.startswith(".dtors")); - assert(Y.startswith(".ctors") || Y.startswith(".dtors")); - X = X.substr(6); - Y = Y.substr(6); - return X < Y; +static bool compCtors(const InputSection *a, const InputSection *b) { + bool beginA = isCrtbegin(a->file->getName()); + bool beginB = isCrtbegin(b->file->getName()); + if (beginA != beginB) + return beginA; + bool endA = isCrtend(a->file->getName()); + bool endB = isCrtend(b->file->getName()); + if (endA != endB) + return endB; + StringRef x = a->name; + StringRef y = b->name; + assert(x.startswith(".ctors") || x.startswith(".dtors")); + assert(y.startswith(".ctors") || y.startswith(".dtors")); + x = x.substr(6); + y = y.substr(6); + return x < y; } // Sorts input sections by the special rules for .ctors and .dtors. // Unfortunately, the rules are different from the one for .{init,fini}_array. // Read the comment above. void OutputSection::sortCtorsDtors() { - assert(SectionCommands.size() == 1); - auto *ISD = cast(SectionCommands[0]); - llvm::stable_sort(ISD->Sections, compCtors); + assert(sectionCommands.size() == 1); + auto *isd = cast(sectionCommands[0]); + llvm::stable_sort(isd->sections, compCtors); } // If an input string is in the form of "foo.N" where N is a number, // return N. Otherwise, returns 65536, which is one greater than the // lowest priority. -int elf::getPriority(StringRef S) { - size_t Pos = S.rfind('.'); - if (Pos == StringRef::npos) +int elf::getPriority(StringRef s) { + size_t pos = s.rfind('.'); + if (pos == StringRef::npos) return 65536; - int V; - if (!to_integer(S.substr(Pos + 1), V, 10)) + int v; + if (!to_integer(s.substr(pos + 1), v, 10)) return 65536; - return V; + return v; } -std::vector elf::getInputSections(OutputSection *OS) { - std::vector Ret; - for (BaseCommand *Base : OS->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end()); - return Ret; +std::vector elf::getInputSections(OutputSection *os) { + std::vector ret; + for (BaseCommand *base : os->sectionCommands) + if (auto *isd = dyn_cast(base)) + ret.insert(ret.end(), isd->sections.begin(), isd->sections.end()); + return ret; } // Sorts input sections by section name suffixes, so that .foo.N comes @@ -394,14 +394,14 @@ // For more detail, read the section of the GCC's manual about init_priority. void OutputSection::sortInitFini() { // Sort sections by priority. - sort([](InputSectionBase *S) { return getPriority(S->Name); }); + sort([](InputSectionBase *s) { return getPriority(s->name); }); } std::array OutputSection::getFiller() { - if (Filler) - return *Filler; - if (Flags & SHF_EXECINSTR) - return Target->TrapInstr; + if (filler) + return *filler; + if (flags & SHF_EXECINSTR) + return target->trapInstr; return {0, 0, 0, 0}; } Index: lld/trunk/ELF/Relocations.h =================================================================== --- lld/trunk/ELF/Relocations.h +++ lld/trunk/ELF/Relocations.h @@ -102,11 +102,11 @@ // Architecture-neutral representation of relocation. struct Relocation { - RelExpr Expr; - RelType Type; - uint64_t Offset; - int64_t Addend; - Symbol *Sym; + RelExpr expr; + RelType type; + uint64_t offset; + int64_t addend; + Symbol *sym; }; // This function writes undefined symbol diagnostics to an internal buffer. @@ -125,57 +125,57 @@ class ThunkCreator { public: // Return true if Thunks have been added to OutputSections - bool createThunks(ArrayRef OutputSections); + bool createThunks(ArrayRef outputSections); // The number of completed passes of createThunks this permits us // to do one time initialization on Pass 0 and put a limit on the // number of times it can be called to prevent infinite loops. - uint32_t Pass = 0; + uint32_t pass = 0; private: - void mergeThunks(ArrayRef OutputSections); + void mergeThunks(ArrayRef outputSections); - ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS, - InputSectionDescription *ISD, uint32_t Type, - uint64_t Src); + ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec, + InputSectionDescription *isd, uint32_t type, + uint64_t src); - ThunkSection *getISThunkSec(InputSection *IS); + ThunkSection *getISThunkSec(InputSection *isec); - void createInitialThunkSections(ArrayRef OutputSections); + void createInitialThunkSections(ArrayRef outputSections); - std::pair getThunk(InputSection *IS, Relocation &Rel, - uint64_t Src); + std::pair getThunk(InputSection *isec, Relocation &rel, + uint64_t src); - ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *, - uint64_t Off); + ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *, + uint64_t off); - bool normalizeExistingThunk(Relocation &Rel, uint64_t Src); + bool normalizeExistingThunk(Relocation &rel, uint64_t src); // Record all the available Thunks for a Symbol llvm::DenseMap, std::vector> - ThunkedSymbolsBySection; - llvm::DenseMap> ThunkedSymbols; + thunkedSymbolsBySection; + llvm::DenseMap> thunkedSymbols; // Find a Thunk from the Thunks symbol definition, we can use this to find // the Thunk from a relocation to the Thunks symbol definition. - llvm::DenseMap Thunks; + llvm::DenseMap thunks; // Track InputSections that have an inline ThunkSection placed in front // an inline ThunkSection may have control fall through to the section below // so we need to make sure that there is only one of them. // The Mips LA25 Thunk is an example of an inline ThunkSection. - llvm::DenseMap ThunkedSections; + llvm::DenseMap thunkedSections; }; // Return a int64_t to make sure we get the sign extension out of the way as // early as possible. template -static inline int64_t getAddend(const typename ELFT::Rel &Rel) { +static inline int64_t getAddend(const typename ELFT::Rel &rel) { return 0; } template -static inline int64_t getAddend(const typename ELFT::Rela &Rel) { - return Rel.r_addend; +static inline int64_t getAddend(const typename ELFT::Rela &rel) { + return rel.r_addend; } } // namespace elf } // namespace lld Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -65,11 +65,11 @@ using namespace lld; using namespace lld::elf; -static Optional getLinkerScriptLocation(const Symbol &Sym) { - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Cmd = dyn_cast(Base)) - if (Cmd->Sym == &Sym) - return Cmd->Location; +static Optional getLinkerScriptLocation(const Symbol &sym) { + for (BaseCommand *base : script->sectionCommands) + if (auto *cmd = dyn_cast(base)) + if (cmd->sym == &sym) + return cmd->location; return None; } @@ -78,19 +78,19 @@ // >>> defined in /home/alice/src/foo.o // >>> referenced by bar.c:12 (/home/alice/src/bar.c:12) // >>> /home/alice/src/bar.o:(.text+0x1) -static std::string getLocation(InputSectionBase &S, const Symbol &Sym, - uint64_t Off) { - std::string Msg = "\n>>> defined in "; - if (Sym.File) - Msg += toString(Sym.File); - else if (Optional Loc = getLinkerScriptLocation(Sym)) - Msg += *Loc; - - Msg += "\n>>> referenced by "; - std::string Src = S.getSrcMsg(Sym, Off); - if (!Src.empty()) - Msg += Src + "\n>>> "; - return Msg + S.getObjMsg(Off); +static std::string getLocation(InputSectionBase &s, const Symbol &sym, + uint64_t off) { + std::string msg = "\n>>> defined in "; + if (sym.file) + msg += toString(sym.file); + else if (Optional loc = getLinkerScriptLocation(sym)) + msg += *loc; + + msg += "\n>>> referenced by "; + std::string src = s.getSrcMsg(sym, off); + if (!src.empty()) + msg += src + "\n>>> "; + return msg + s.getObjMsg(off); } namespace { @@ -119,10 +119,10 @@ // There are fewer than 64 RelExpr's, so we can represent any set of // RelExpr's as a constant bit mask and test for membership with a // couple cheap bitwise operations. -template bool oneof(RelExpr Expr) { - assert(0 <= Expr && (int)Expr < 64 && +template bool oneof(RelExpr expr) { + assert(0 <= expr && (int)expr < 64 && "RelExpr is too large for 64-bit mask!"); - return (uint64_t(1) << Expr) & RelExprMaskBuilder::build(); + return (uint64_t(1) << expr) & RelExprMaskBuilder::build(); } // This function is similar to the `handleTlsRelocation`. MIPS does not @@ -131,17 +131,17 @@ // pollute other `handleTlsRelocation` by MIPS `ifs` statements. // Mips has a custom MipsGotSection that handles the writing of GOT entries // without dynamic relocations. -static unsigned handleMipsTlsRelocation(RelType Type, Symbol &Sym, - InputSectionBase &C, uint64_t Offset, - int64_t Addend, RelExpr Expr) { - if (Expr == R_MIPS_TLSLD) { - In.MipsGot->addTlsIndex(*C.File); - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); +static unsigned handleMipsTlsRelocation(RelType type, Symbol &sym, + InputSectionBase &c, uint64_t offset, + int64_t addend, RelExpr expr) { + if (expr == R_MIPS_TLSLD) { + in.mipsGot->addTlsIndex(*c.file); + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } - if (Expr == R_MIPS_TLSGD) { - In.MipsGot->addDynTlsEntry(*C.File, Sym); - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + if (expr == R_MIPS_TLSGD) { + in.mipsGot->addDynTlsEntry(*c.file, sym); + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } return 0; @@ -156,28 +156,28 @@ // Returns the number of relocations processed. template static unsigned -handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, - typename ELFT::uint Offset, int64_t Addend, RelExpr Expr) { - if (!Sym.isTls()) +handleTlsRelocation(RelType type, Symbol &sym, InputSectionBase &c, + typename ELFT::uint offset, int64_t addend, RelExpr expr) { + if (!sym.isTls()) return 0; - if (Config->EMachine == EM_MIPS) - return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr); + if (config->emachine == EM_MIPS) + return handleMipsTlsRelocation(type, sym, c, offset, addend, expr); if (oneof( - Expr) && - Config->Shared) { - if (In.Got->addDynTlsEntry(Sym)) { - uint64_t Off = In.Got->getGlobalDynOffset(Sym); - Main->RelaDyn->addReloc( - {Target->TlsDescRel, In.Got, Off, !Sym.IsPreemptible, &Sym, 0}); + expr) && + config->shared) { + if (in.got->addDynTlsEntry(sym)) { + uint64_t off = in.got->getGlobalDynOffset(sym); + mainPart->relaDyn->addReloc( + {target->tlsDescRel, in.got, off, !sym.isPreemptible, &sym, 0}); } - if (Expr != R_TLSDESC_CALL) - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + if (expr != R_TLSDESC_CALL) + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } - bool CanRelax = Config->EMachine != EM_ARM && Config->EMachine != EM_RISCV; + bool canRelax = config->emachine != EM_ARM && config->emachine != EM_RISCV; // If we are producing an executable and the symbol is non-preemptable, it // must be defined and the code sequence can be relaxed to use Local-Exec. @@ -186,118 +186,118 @@ // we can omit the DTPMOD dynamic relocations and resolve them at link time // because them are always 1. This may be necessary for static linking as // DTPMOD may not be expected at load time. - bool IsLocalInExecutable = !Sym.IsPreemptible && !Config->Shared; + bool isLocalInExecutable = !sym.isPreemptible && !config->shared; // Local Dynamic is for access to module local TLS variables, while still // being suitable for being dynamically loaded via dlopen. GOT[e0] is the // module index, with a special value of 0 for the current module. GOT[e1] is // unused. There only needs to be one module index entry. if (oneof( - Expr)) { + expr)) { // Local-Dynamic relocs can be relaxed to Local-Exec. - if (CanRelax && !Config->Shared) { - C.Relocations.push_back( - {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type, - Offset, Addend, &Sym}); - return Target->getTlsGdRelaxSkip(Type); + if (canRelax && !config->shared) { + c.relocations.push_back( + {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_LD_TO_LE), type, + offset, addend, &sym}); + return target->getTlsGdRelaxSkip(type); } - if (Expr == R_TLSLD_HINT) + if (expr == R_TLSLD_HINT) return 1; - if (In.Got->addTlsIndex()) { - if (IsLocalInExecutable) - In.Got->Relocations.push_back( - {R_ADDEND, Target->SymbolicRel, In.Got->getTlsIndexOff(), 1, &Sym}); + if (in.got->addTlsIndex()) { + if (isLocalInExecutable) + in.got->relocations.push_back( + {R_ADDEND, target->symbolicRel, in.got->getTlsIndexOff(), 1, &sym}); else - Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, - In.Got->getTlsIndexOff(), nullptr); + mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, in.got, + in.got->getTlsIndexOff(), nullptr); } - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } // Local-Dynamic relocs can be relaxed to Local-Exec. - if (Expr == R_DTPREL && !Config->Shared) { - C.Relocations.push_back( - {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type, - Offset, Addend, &Sym}); + if (expr == R_DTPREL && !config->shared) { + c.relocations.push_back( + {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_LD_TO_LE), type, + offset, addend, &sym}); return 1; } // Local-Dynamic sequence where offset of tls variable relative to dynamic // thread pointer is stored in the got. This cannot be relaxed to Local-Exec. - if (Expr == R_TLSLD_GOT_OFF) { - if (!Sym.isInGot()) { - In.Got->addEntry(Sym); - uint64_t Off = Sym.getGotOffset(); - In.Got->Relocations.push_back( - {R_ABS, Target->TlsOffsetRel, Off, 0, &Sym}); + if (expr == R_TLSLD_GOT_OFF) { + if (!sym.isInGot()) { + in.got->addEntry(sym); + uint64_t off = sym.getGotOffset(); + in.got->relocations.push_back( + {R_ABS, target->tlsOffsetRel, off, 0, &sym}); } - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } if (oneof(Expr)) { - if (!CanRelax || Config->Shared) { - if (In.Got->addDynTlsEntry(Sym)) { - uint64_t Off = In.Got->getGlobalDynOffset(Sym); + R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) { + if (!canRelax || config->shared) { + if (in.got->addDynTlsEntry(sym)) { + uint64_t off = in.got->getGlobalDynOffset(sym); - if (IsLocalInExecutable) + if (isLocalInExecutable) // Write one to the GOT slot. - In.Got->Relocations.push_back( - {R_ADDEND, Target->SymbolicRel, Off, 1, &Sym}); + in.got->relocations.push_back( + {R_ADDEND, target->symbolicRel, off, 1, &sym}); else - Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, Off, &Sym); + mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, in.got, off, &sym); // If the symbol is preemptible we need the dynamic linker to write // the offset too. - uint64_t OffsetOff = Off + Config->Wordsize; - if (Sym.IsPreemptible) - Main->RelaDyn->addReloc(Target->TlsOffsetRel, In.Got, OffsetOff, - &Sym); + uint64_t offsetOff = off + config->wordsize; + if (sym.isPreemptible) + mainPart->relaDyn->addReloc(target->tlsOffsetRel, in.got, offsetOff, + &sym); else - In.Got->Relocations.push_back( - {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Sym}); + in.got->relocations.push_back( + {R_ABS, target->tlsOffsetRel, offsetOff, 0, &sym}); } - C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + c.relocations.push_back({expr, type, offset, addend, &sym}); return 1; } // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec // depending on the symbol being locally defined or not. - if (Sym.IsPreemptible) { - C.Relocations.push_back( - {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type, - Offset, Addend, &Sym}); - if (!Sym.isInGot()) { - In.Got->addEntry(Sym); - Main->RelaDyn->addReloc(Target->TlsGotRel, In.Got, Sym.getGotOffset(), - &Sym); + if (sym.isPreemptible) { + c.relocations.push_back( + {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_GD_TO_IE), type, + offset, addend, &sym}); + if (!sym.isInGot()) { + in.got->addEntry(sym); + mainPart->relaDyn->addReloc(target->tlsGotRel, in.got, sym.getGotOffset(), + &sym); } } else { - C.Relocations.push_back( - {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type, - Offset, Addend, &Sym}); + c.relocations.push_back( + {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_GD_TO_LE), type, + offset, addend, &sym}); } - return Target->getTlsGdRelaxSkip(Type); + return target->getTlsGdRelaxSkip(type); } // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally // defined. if (oneof(Expr) && - CanRelax && IsLocalInExecutable) { - C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym}); + R_TLSIE_HINT>(expr) && + canRelax && isLocalInExecutable) { + c.relocations.push_back({R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym}); return 1; } - if (Expr == R_TLSIE_HINT) + if (expr == R_TLSIE_HINT) return 1; return 0; } -static RelType getMipsPairType(RelType Type, bool IsLocal) { - switch (Type) { +static RelType getMipsPairType(RelType type, bool isLocal) { + switch (type) { case R_MIPS_HI16: return R_MIPS_LO16; case R_MIPS_GOT16: @@ -309,9 +309,9 @@ // the high 16 bits of the symbol's value. A paired R_MIPS_LO16 // relocations handle low 16 bits of the address. That allows // to allocate only one GOT entry for every 64 KBytes of local data. - return IsLocal ? R_MIPS_LO16 : R_MIPS_NONE; + return isLocal ? R_MIPS_LO16 : R_MIPS_NONE; case R_MICROMIPS_GOT16: - return IsLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE; + return isLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE; case R_MIPS_PCHI16: return R_MIPS_PCLO16; case R_MICROMIPS_HI16: @@ -323,38 +323,38 @@ // True if non-preemptable symbol always has the same value regardless of where // the DSO is loaded. -static bool isAbsolute(const Symbol &Sym) { - if (Sym.isUndefWeak()) +static bool isAbsolute(const Symbol &sym) { + if (sym.isUndefWeak()) return true; - if (const auto *DR = dyn_cast(&Sym)) - return DR->Section == nullptr; // Absolute symbol. + if (const auto *dr = dyn_cast(&sym)) + return dr->section == nullptr; // Absolute symbol. return false; } -static bool isAbsoluteValue(const Symbol &Sym) { - return isAbsolute(Sym) || Sym.isTls(); +static bool isAbsoluteValue(const Symbol &sym) { + return isAbsolute(sym) || sym.isTls(); } // Returns true if Expr refers a PLT entry. -static bool needsPlt(RelExpr Expr) { - return oneof(Expr); +static bool needsPlt(RelExpr expr) { + return oneof(expr); } // Returns true if Expr refers a GOT entry. Note that this function // returns false for TLS variables even though they need GOT, because // TLS variables uses GOT differently than the regular variables. -static bool needsGot(RelExpr Expr) { +static bool needsGot(RelExpr expr) { return oneof(Expr); + R_GOT_PC, R_GOTPLT>(expr); } // True if this expression is of the form Sym - X, where X is a position in the // file (PC, or GOT for example). -static bool isRelExpr(RelExpr Expr) { +static bool isRelExpr(RelExpr expr) { return oneof(Expr); + R_RISCV_PC_INDIRECT>(expr); } // Returns true if a given relocation can be computed at link-time. @@ -366,8 +366,8 @@ // // If this function returns false, that means we need to emit a // dynamic relocation so that the relocation will be fixed at load-time. -static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, - InputSectionBase &S, uint64_t RelOff) { +static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym, + InputSectionBase &s, uint64_t relOff) { // These expressions always compute a constant if (oneof(E)) + R_TLSIE_HINT>(e)) return true; // These never do, except if the entire file is position dependent or if // only the low bits are used. - if (E == R_GOT || E == R_PLT || E == R_TLSDESC) - return Target->usesOnlyLowPageBits(Type) || !Config->Pic; + if (e == R_GOT || e == R_PLT || e == R_TLSDESC) + return target->usesOnlyLowPageBits(type) || !config->isPic; - if (Sym.IsPreemptible) + if (sym.isPreemptible) return false; - if (!Config->Pic) + if (!config->isPic) return true; // The size of a non preemptible symbol is a constant. - if (E == R_SIZE) + if (e == R_SIZE) return true; // For the target and the relocation, we want to know if they are // absolute or relative. - bool AbsVal = isAbsoluteValue(Sym); - bool RelE = isRelExpr(E); - if (AbsVal && !RelE) + bool absVal = isAbsoluteValue(sym); + bool relE = isRelExpr(e); + if (absVal && !relE) return true; - if (!AbsVal && RelE) + if (!absVal && relE) return true; - if (!AbsVal && !RelE) - return Target->usesOnlyLowPageBits(Type); + if (!absVal && !relE) + return target->usesOnlyLowPageBits(type); // Relative relocation to an absolute value. This is normally unrepresentable, // but if the relocation refers to a weak undefined symbol, we allow it to @@ -412,22 +412,22 @@ // Another special case is MIPS _gp_disp symbol which represents offset // between start of a function and '_gp' value and defined as absolute just // to simplify the code. - assert(AbsVal && RelE); - if (Sym.isUndefWeak()) + assert(absVal && relE); + if (sym.isUndefWeak()) return true; // We set the final symbols values for linker script defined symbols later. // They always can be computed as a link time constant. - if (Sym.ScriptDefined) + if (sym.scriptDefined) return true; - error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + - toString(Sym) + getLocation(S, Sym, RelOff)); + error("relocation " + toString(type) + " cannot refer to absolute symbol: " + + toString(sym) + getLocation(s, sym, relOff)); return true; } -static RelExpr toPlt(RelExpr Expr) { - switch (Expr) { +static RelExpr toPlt(RelExpr expr) { + switch (expr) { case R_PPC64_CALL: return R_PPC64_CALL_PLT; case R_PC: @@ -435,14 +435,14 @@ case R_ABS: return R_PLT; default: - return Expr; + return expr; } } -static RelExpr fromPlt(RelExpr Expr) { +static RelExpr fromPlt(RelExpr expr) { // We decided not to use a plt. Optimize a reference to the plt to a // reference to the symbol itself. - switch (Expr) { + switch (expr) { case R_PLT_PC: case R_PPC32_PLTREL: return R_PC; @@ -451,21 +451,21 @@ case R_PLT: return R_ABS; default: - return Expr; + return expr; } } // Returns true if a given shared symbol is in a read-only segment in a DSO. -template static bool isReadOnly(SharedSymbol &SS) { +template static bool isReadOnly(SharedSymbol &ss) { using Elf_Phdr = typename ELFT::Phdr; // Determine if the symbol is read-only by scanning the DSO's program headers. - const SharedFile &File = SS.getFile(); - for (const Elf_Phdr &Phdr : - check(File.template getObj().program_headers())) - if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && - !(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr && - SS.Value < Phdr.p_vaddr + Phdr.p_memsz) + const SharedFile &file = ss.getFile(); + for (const Elf_Phdr &phdr : + check(file.template getObj().program_headers())) + if ((phdr.p_type == ELF::PT_LOAD || phdr.p_type == ELF::PT_GNU_RELRO) && + !(phdr.p_flags & ELF::PF_W) && ss.value >= phdr.p_vaddr && + ss.value < phdr.p_vaddr + phdr.p_memsz) return true; return false; } @@ -476,22 +476,22 @@ // them are copied by a copy relocation, all of them need to be copied. // Otherwise, they would refer to different places at runtime. template -static SmallSet getSymbolsAt(SharedSymbol &SS) { +static SmallSet getSymbolsAt(SharedSymbol &ss) { using Elf_Sym = typename ELFT::Sym; - SharedFile &File = SS.getFile(); + SharedFile &file = ss.getFile(); - SmallSet Ret; - for (const Elf_Sym &S : File.template getGlobalELFSyms()) { - if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS || - S.getType() == STT_TLS || S.st_value != SS.Value) + SmallSet ret; + for (const Elf_Sym &s : file.template getGlobalELFSyms()) { + if (s.st_shndx == SHN_UNDEF || s.st_shndx == SHN_ABS || + s.getType() == STT_TLS || s.st_value != ss.value) continue; - StringRef Name = check(S.getName(File.getStringTable())); - Symbol *Sym = Symtab->find(Name); - if (auto *Alias = dyn_cast_or_null(Sym)) - Ret.insert(Alias); + StringRef name = check(s.getName(file.getStringTable())); + Symbol *sym = symtab->find(name); + if (auto *alias = dyn_cast_or_null(sym)) + ret.insert(alias); } - return Ret; + return ret; } // When a symbol is copy relocated or we create a canonical plt entry, it is @@ -499,21 +499,21 @@ // in .bss and in the case of a canonical plt entry it is in .plt. This function // replaces the existing symbol with a Defined pointing to the appropriate // location. -static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value, - uint64_t Size) { - Symbol Old = Sym; - - Sym.replace(Defined{Sym.File, Sym.getName(), Sym.Binding, Sym.StOther, - Sym.Type, Value, Size, Sec}); - - Sym.PltIndex = Old.PltIndex; - Sym.GotIndex = Old.GotIndex; - Sym.VerdefIndex = Old.VerdefIndex; - Sym.PPC64BranchltIndex = Old.PPC64BranchltIndex; - Sym.IsPreemptible = true; - Sym.ExportDynamic = true; - Sym.IsUsedInRegularObj = true; - Sym.Used = true; +static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value, + uint64_t size) { + Symbol old = sym; + + sym.replace(Defined{sym.file, sym.getName(), sym.binding, sym.stOther, + sym.type, value, size, sec}); + + sym.pltIndex = old.pltIndex; + sym.gotIndex = old.gotIndex; + sym.verdefIndex = old.verdefIndex; + sym.ppc64BranchltIndex = old.ppc64BranchltIndex; + sym.isPreemptible = true; + sym.exportDynamic = true; + sym.isUsedInRegularObj = true; + sym.used = true; } // Reserve space in .bss or .bss.rel.ro for copy relocation. @@ -558,29 +558,29 @@ // to the variable in .bss. This kind of issue is sometimes very hard to // debug. What's a solution? Instead of exporting a varaible V from a DSO, // define an accessor getV(). -template static void addCopyRelSymbol(SharedSymbol &SS) { +template static void addCopyRelSymbol(SharedSymbol &ss) { // Copy relocation against zero-sized symbol doesn't make sense. - uint64_t SymSize = SS.getSize(); - if (SymSize == 0 || SS.Alignment == 0) - fatal("cannot create a copy relocation for symbol " + toString(SS)); + uint64_t symSize = ss.getSize(); + if (symSize == 0 || ss.alignment == 0) + fatal("cannot create a copy relocation for symbol " + toString(ss)); // See if this symbol is in a read-only segment. If so, preserve the symbol's // memory protection by reserving space in the .bss.rel.ro section. - bool IsRO = isReadOnly(SS); - BssSection *Sec = - make(IsRO ? ".bss.rel.ro" : ".bss", SymSize, SS.Alignment); - if (IsRO) - In.BssRelRo->getParent()->addSection(Sec); + bool isRO = isReadOnly(ss); + BssSection *sec = + make(isRO ? ".bss.rel.ro" : ".bss", symSize, ss.alignment); + if (isRO) + in.bssRelRo->getParent()->addSection(sec); else - In.Bss->getParent()->addSection(Sec); + in.bss->getParent()->addSection(sec); // Look through the DSO's dynamic symbol table for aliases and create a // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. - for (SharedSymbol *Sym : getSymbolsAt(SS)) - replaceWithDefined(*Sym, Sec, 0, Sym->Size); + for (SharedSymbol *sym : getSymbolsAt(ss)) + replaceWithDefined(*sym, sec, 0, sym->size); - Main->RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); + mainPart->relaDyn->addReloc(target->copyRel, sec, 0, &ss); } // MIPS has an odd notion of "paired" relocations to calculate addends. @@ -588,34 +588,34 @@ // R_MIPS_LO16 relocation after that, and an addend is calculated using // the two relocations. template -static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End, - InputSectionBase &Sec, RelExpr Expr, - bool IsLocal) { - if (Expr == R_MIPS_GOTREL && IsLocal) - return Sec.getFile()->MipsGp0; +static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end, + InputSectionBase &sec, RelExpr expr, + bool isLocal) { + if (expr == R_MIPS_GOTREL && isLocal) + return sec.getFile()->mipsGp0; // The ABI says that the paired relocation is used only for REL. // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf if (RelTy::IsRela) return 0; - RelType Type = Rel.getType(Config->IsMips64EL); - uint32_t PairTy = getMipsPairType(Type, IsLocal); - if (PairTy == R_MIPS_NONE) + RelType type = rel.getType(config->isMips64EL); + uint32_t pairTy = getMipsPairType(type, isLocal); + if (pairTy == R_MIPS_NONE) return 0; - const uint8_t *Buf = Sec.data().data(); - uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); + const uint8_t *buf = sec.data().data(); + uint32_t symIndex = rel.getSymbol(config->isMips64EL); // To make things worse, paired relocations might not be contiguous in // the relocation table, so we need to do linear search. *sigh* - for (const RelTy *RI = &Rel; RI != End; ++RI) - if (RI->getType(Config->IsMips64EL) == PairTy && - RI->getSymbol(Config->IsMips64EL) == SymIndex) - return Target->getImplicitAddend(Buf + RI->r_offset, PairTy); + for (const RelTy *ri = &rel; ri != end; ++ri) + if (ri->getType(config->isMips64EL) == pairTy && + ri->getSymbol(config->isMips64EL) == symIndex) + return target->getImplicitAddend(buf + ri->r_offset, pairTy); - warn("can't find matching " + toString(PairTy) + " relocation for " + - toString(Type)); + warn("can't find matching " + toString(pairTy) + " relocation for " + + toString(type)); return 0; } @@ -623,82 +623,82 @@ // is in a relocation itself. If it is REL, we need to read it from an // input section. template -static int64_t computeAddend(const RelTy &Rel, const RelTy *End, - InputSectionBase &Sec, RelExpr Expr, - bool IsLocal) { - int64_t Addend; - RelType Type = Rel.getType(Config->IsMips64EL); +static int64_t computeAddend(const RelTy &rel, const RelTy *end, + InputSectionBase &sec, RelExpr expr, + bool isLocal) { + int64_t addend; + RelType type = rel.getType(config->isMips64EL); if (RelTy::IsRela) { - Addend = getAddend(Rel); + addend = getAddend(rel); } else { - const uint8_t *Buf = Sec.data().data(); - Addend = Target->getImplicitAddend(Buf + Rel.r_offset, Type); + const uint8_t *buf = sec.data().data(); + addend = target->getImplicitAddend(buf + rel.r_offset, type); } - if (Config->EMachine == EM_PPC64 && Config->Pic && Type == R_PPC64_TOC) - Addend += getPPC64TocBase(); - if (Config->EMachine == EM_MIPS) - Addend += computeMipsAddend(Rel, End, Sec, Expr, IsLocal); + if (config->emachine == EM_PPC64 && config->isPic && type == R_PPC64_TOC) + addend += getPPC64TocBase(); + if (config->emachine == EM_MIPS) + addend += computeMipsAddend(rel, end, sec, expr, isLocal); - return Addend; + return addend; } // Custom error message if Sym is defined in a discarded section. template -static std::string maybeReportDiscarded(Undefined &Sym) { - auto *File = dyn_cast_or_null>(Sym.File); - if (!File || !Sym.DiscardedSecIdx || - File->getSections()[Sym.DiscardedSecIdx] != &InputSection::Discarded) +static std::string maybeReportDiscarded(Undefined &sym) { + auto *file = dyn_cast_or_null>(sym.file); + if (!file || !sym.discardedSecIdx || + file->getSections()[sym.discardedSecIdx] != &InputSection::discarded) return ""; - ArrayRef> ObjSections = - CHECK(File->getObj().sections(), File); + ArrayRef> objSections = + CHECK(file->getObj().sections(), file); - std::string Msg; - if (Sym.Type == ELF::STT_SECTION) { - Msg = "relocation refers to a discarded section: "; - Msg += CHECK( - File->getObj().getSectionName(&ObjSections[Sym.DiscardedSecIdx]), File); + std::string msg; + if (sym.type == ELF::STT_SECTION) { + msg = "relocation refers to a discarded section: "; + msg += CHECK( + file->getObj().getSectionName(&objSections[sym.discardedSecIdx]), file); } else { - Msg = "relocation refers to a symbol in a discarded section: " + - toString(Sym); + msg = "relocation refers to a symbol in a discarded section: " + + toString(sym); } - Msg += "\n>>> defined in " + toString(File); + msg += "\n>>> defined in " + toString(file); - Elf_Shdr_Impl ELFSec = ObjSections[Sym.DiscardedSecIdx - 1]; - if (ELFSec.sh_type != SHT_GROUP) - return Msg; + Elf_Shdr_Impl elfSec = objSections[sym.discardedSecIdx - 1]; + if (elfSec.sh_type != SHT_GROUP) + return msg; // If the discarded section is a COMDAT. - StringRef Signature = File->getShtGroupSignature(ObjSections, ELFSec); - if (const InputFile *Prevailing = - Symtab->ComdatGroups.lookup(CachedHashStringRef(Signature))) - Msg += "\n>>> section group signature: " + Signature.str() + - "\n>>> prevailing definition is in " + toString(Prevailing); - return Msg; + StringRef signature = file->getShtGroupSignature(objSections, elfSec); + if (const InputFile *prevailing = + symtab->comdatGroups.lookup(CachedHashStringRef(signature))) + msg += "\n>>> section group signature: " + signature.str() + + "\n>>> prevailing definition is in " + toString(prevailing); + return msg; } // Undefined diagnostics are collected in a vector and emitted once all of // them are known, so that some postprocessing on the list of undefined symbols // can happen before lld emits diagnostics. struct UndefinedDiag { - Symbol *Sym; + Symbol *sym; struct Loc { - InputSectionBase *Sec; - uint64_t Offset; + InputSectionBase *sec; + uint64_t offset; }; - std::vector Locs; - bool IsWarning; + std::vector locs; + bool isWarning; }; -static std::vector Undefs; +static std::vector undefs; template -static void reportUndefinedSymbol(const UndefinedDiag &Undef) { - Symbol &Sym = *Undef.Sym; +static void reportUndefinedSymbol(const UndefinedDiag &undef) { + Symbol &sym = *undef.sym; - auto Visibility = [&]() -> std::string { - switch (Sym.Visibility) { + auto visibility = [&]() -> std::string { + switch (sym.visibility) { case STV_INTERNAL: return "internal "; case STV_HIDDEN: @@ -710,71 +710,71 @@ } }; - std::string Msg = maybeReportDiscarded(cast(Sym)); - if (Msg.empty()) - Msg = "undefined " + Visibility() + "symbol: " + toString(Sym); - - const size_t MaxUndefReferences = 10; - size_t I = 0; - for (UndefinedDiag::Loc L : Undef.Locs) { - if (I >= MaxUndefReferences) + std::string msg = maybeReportDiscarded(cast(sym)); + if (msg.empty()) + msg = "undefined " + visibility() + "symbol: " + toString(sym); + + const size_t maxUndefReferences = 10; + size_t i = 0; + for (UndefinedDiag::Loc l : undef.locs) { + if (i >= maxUndefReferences) break; - InputSectionBase &Sec = *L.Sec; - uint64_t Offset = L.Offset; + InputSectionBase &sec = *l.sec; + uint64_t offset = l.offset; - Msg += "\n>>> referenced by "; - std::string Src = Sec.getSrcMsg(Sym, Offset); - if (!Src.empty()) - Msg += Src + "\n>>> "; - Msg += Sec.getObjMsg(Offset); - I++; + msg += "\n>>> referenced by "; + std::string src = sec.getSrcMsg(sym, offset); + if (!src.empty()) + msg += src + "\n>>> "; + msg += sec.getObjMsg(offset); + i++; } - if (I < Undef.Locs.size()) - Msg += ("\n>>> referenced " + Twine(Undef.Locs.size() - I) + " more times") + if (i < undef.locs.size()) + msg += ("\n>>> referenced " + Twine(undef.locs.size() - i) + " more times") .str(); - if (Sym.getName().startswith("_ZTV")) - Msg += "\nthe vtable symbol may be undefined because the class is missing " + if (sym.getName().startswith("_ZTV")) + msg += "\nthe vtable symbol may be undefined because the class is missing " "its key function (see https://lld.llvm.org/missingkeyfunction)"; - if (Undef.IsWarning) - warn(Msg); + if (undef.isWarning) + warn(msg); else - error(Msg); + error(msg); } template void elf::reportUndefinedSymbols() { // Find the first "undefined symbol" diagnostic for each diagnostic, and // collect all "referenced from" lines at the first diagnostic. - DenseMap FirstRef; - for (UndefinedDiag &Undef : Undefs) { - assert(Undef.Locs.size() == 1); - if (UndefinedDiag *Canon = FirstRef.lookup(Undef.Sym)) { - Canon->Locs.push_back(Undef.Locs[0]); - Undef.Locs.clear(); + DenseMap firstRef; + for (UndefinedDiag &undef : undefs) { + assert(undef.locs.size() == 1); + if (UndefinedDiag *canon = firstRef.lookup(undef.sym)) { + canon->locs.push_back(undef.locs[0]); + undef.locs.clear(); } else - FirstRef[Undef.Sym] = &Undef; + firstRef[undef.sym] = &undef; } - for (const UndefinedDiag &Undef : Undefs) { - if (!Undef.Locs.empty()) - reportUndefinedSymbol(Undef); + for (const UndefinedDiag &undef : undefs) { + if (!undef.locs.empty()) + reportUndefinedSymbol(undef); } - Undefs.clear(); + undefs.clear(); } // Report an undefined symbol if necessary. // Returns true if the undefined symbol will produce an error message. template -static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, - uint64_t Offset) { - if (!Sym.isUndefined() || Sym.isWeak()) +static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec, + uint64_t offset) { + if (!sym.isUndefined() || sym.isWeak()) return false; - bool CanBeExternal = !Sym.isLocal() && Sym.computeBinding() != STB_LOCAL && - Sym.Visibility == STV_DEFAULT; - if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) + bool canBeExternal = !sym.isLocal() && sym.computeBinding() != STB_LOCAL && + sym.visibility == STV_DEFAULT; + if (config->unresolvedSymbols == UnresolvedPolicy::Ignore && canBeExternal) return false; // clang (as of 2019-06-12) / gcc (as of 8.2.1) PPC64 may emit a .rela.toc @@ -782,15 +782,15 @@ // .toc and the .rela.toc are incorrectly not placed in the comdat. The ELF // spec says references from outside the group to a STB_LOCAL symbol are not // allowed. Work around the bug. - if (Config->EMachine == EM_PPC64 && - cast(Sym).DiscardedSecIdx != 0 && Sec.Name == ".toc") + if (config->emachine == EM_PPC64 && + cast(sym).discardedSecIdx != 0 && sec.name == ".toc") return false; - bool IsWarning = - (Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || - Config->NoinhibitExec; - Undefs.push_back({&Sym, {{&Sec, Offset}}, IsWarning}); - return !IsWarning; + bool isWarning = + (config->unresolvedSymbols == UnresolvedPolicy::Warn && canBeExternal) || + config->noinhibitExec; + undefs.push_back({&sym, {{&sec, offset}}, isWarning}); + return !isWarning; } // MIPS N32 ABI treats series of successive relocations with the same offset @@ -798,14 +798,14 @@ // packs all relocations into the single relocation record. Here we emulate // this for the N32 ABI. Iterate over relocation with the same offset and put // theirs types into the single bit-set. -template static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) { - RelType Type = 0; - uint64_t Offset = Rel->r_offset; - - int N = 0; - while (Rel != End && Rel->r_offset == Offset) - Type |= (Rel++)->getType(Config->IsMips64EL) << (8 * N++); - return Type; +template static RelType getMipsN32RelType(RelTy *&rel, RelTy *end) { + RelType type = 0; + uint64_t offset = rel->r_offset; + + int n = 0; + while (rel != end && rel->r_offset == offset) + type |= (rel++)->getType(config->isMips64EL) << (8 * n++); + return type; } // .eh_frame sections are mergeable input sections, so their input @@ -822,42 +822,42 @@ namespace { class OffsetGetter { public: - explicit OffsetGetter(InputSectionBase &Sec) { - if (auto *Eh = dyn_cast(&Sec)) - Pieces = Eh->Pieces; + explicit OffsetGetter(InputSectionBase &sec) { + if (auto *eh = dyn_cast(&sec)) + pieces = eh->pieces; } // Translates offsets in input sections to offsets in output sections. // Given offset must increase monotonically. We assume that Piece is // sorted by InputOff. - uint64_t get(uint64_t Off) { - if (Pieces.empty()) - return Off; - - while (I != Pieces.size() && Pieces[I].InputOff + Pieces[I].Size <= Off) - ++I; - if (I == Pieces.size()) + uint64_t get(uint64_t off) { + if (pieces.empty()) + return off; + + while (i != pieces.size() && pieces[i].inputOff + pieces[i].size <= off) + ++i; + if (i == pieces.size()) fatal(".eh_frame: relocation is not in any piece"); // Pieces must be contiguous, so there must be no holes in between. - assert(Pieces[I].InputOff <= Off && "Relocation not in any piece"); + assert(pieces[i].inputOff <= off && "Relocation not in any piece"); // Offset -1 means that the piece is dead (i.e. garbage collected). - if (Pieces[I].OutputOff == -1) + if (pieces[i].outputOff == -1) return -1; - return Pieces[I].OutputOff + Off - Pieces[I].InputOff; + return pieces[i].outputOff + off - pieces[i].inputOff; } private: - ArrayRef Pieces; - size_t I = 0; + ArrayRef pieces; + size_t i = 0; }; } // namespace -static void addRelativeReloc(InputSectionBase *IS, uint64_t OffsetInSec, - Symbol *Sym, int64_t Addend, RelExpr Expr, - RelType Type) { - Partition &Part = IS->getPartition(); +static void addRelativeReloc(InputSectionBase *isec, uint64_t offsetInSec, + Symbol *sym, int64_t addend, RelExpr expr, + RelType type) { + Partition &part = isec->getPartition(); // Add a relative relocation. If RelrDyn section is enabled, and the // relocation offset is guaranteed to be even, add the relocation to @@ -865,29 +865,29 @@ // RelrDyn sections don't support odd offsets. Also, RelrDyn sections // don't store the addend values, so we must write it to the relocated // address. - if (Part.RelrDyn && IS->Alignment >= 2 && OffsetInSec % 2 == 0) { - IS->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym}); - Part.RelrDyn->Relocs.push_back({IS, OffsetInSec}); + if (part.relrDyn && isec->alignment >= 2 && offsetInSec % 2 == 0) { + isec->relocations.push_back({expr, type, offsetInSec, addend, sym}); + part.relrDyn->relocs.push_back({isec, offsetInSec}); return; } - Part.RelaDyn->addReloc(Target->RelativeRel, IS, OffsetInSec, Sym, Addend, - Expr, Type); + part.relaDyn->addReloc(target->relativeRel, isec, offsetInSec, sym, addend, + expr, type); } template -static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt, - RelocationBaseSection *Rel, RelType Type, Symbol &Sym) { - Plt->addEntry(Sym); - GotPlt->addEntry(Sym); - Rel->addReloc( - {Type, GotPlt, Sym.getGotPltOffset(), !Sym.IsPreemptible, &Sym, 0}); +static void addPltEntry(PltSection *plt, GotPltSection *gotPlt, + RelocationBaseSection *rel, RelType type, Symbol &sym) { + plt->addEntry(sym); + gotPlt->addEntry(sym); + rel->addReloc( + {type, gotPlt, sym.getGotPltOffset(), !sym.isPreemptible, &sym, 0}); } -static void addGotEntry(Symbol &Sym) { - In.Got->addEntry(Sym); +static void addGotEntry(Symbol &sym) { + in.got->addEntry(sym); - RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS; - uint64_t Off = Sym.getGotOffset(); + RelExpr expr = sym.isTls() ? R_TLS : R_ABS; + uint64_t off = sym.getGotOffset(); // If a GOT slot value can be calculated at link-time, which is now, // we can just fill that out. @@ -896,42 +896,42 @@ // add a static relocation to a Relocations vector so that // InputSection::relocate will do the work for us. We may be able // to just write a value now, but it is a TODO.) - bool IsLinkTimeConstant = - !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym)); - if (IsLinkTimeConstant) { - In.Got->Relocations.push_back({Expr, Target->SymbolicRel, Off, 0, &Sym}); + bool isLinkTimeConstant = + !sym.isPreemptible && (!config->isPic || isAbsolute(sym)); + if (isLinkTimeConstant) { + in.got->relocations.push_back({expr, target->symbolicRel, off, 0, &sym}); return; } // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that // the GOT slot will be fixed at load-time. - if (!Sym.isTls() && !Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) { - addRelativeReloc(In.Got, Off, &Sym, 0, R_ABS, Target->SymbolicRel); + if (!sym.isTls() && !sym.isPreemptible && config->isPic && !isAbsolute(sym)) { + addRelativeReloc(in.got, off, &sym, 0, R_ABS, target->symbolicRel); return; } - Main->RelaDyn->addReloc( - Sym.isTls() ? Target->TlsGotRel : Target->GotRel, In.Got, Off, &Sym, 0, - Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->SymbolicRel); + mainPart->relaDyn->addReloc( + sym.isTls() ? target->tlsGotRel : target->gotRel, in.got, off, &sym, 0, + sym.isPreemptible ? R_ADDEND : R_ABS, target->symbolicRel); } // Return true if we can define a symbol in the executable that // contains the value/function of a symbol defined in a shared // library. -static bool canDefineSymbolInExecutable(Symbol &Sym) { +static bool canDefineSymbolInExecutable(Symbol &sym) { // If the symbol has default visibility the symbol defined in the // executable will preempt it. // Note that we want the visibility of the shared symbol itself, not // the visibility of the symbol in the output file we are producing. That is // why we use Sym.StOther. - if ((Sym.StOther & 0x3) == STV_DEFAULT) + if ((sym.stOther & 0x3) == STV_DEFAULT) return true; // If we are allowed to break address equality of functions, defining // a plt entry will allow the program to call the function in the // .so, but the .so and the executable will no agree on the address // of the function. Similar logic for objects. - return ((Sym.isFunc() && Config->IgnoreFunctionAddressEquality) || - (Sym.isObject() && Config->IgnoreDataAddressEquality)); + return ((sym.isFunc() && config->ignoreFunctionAddressEquality) || + (sym.isObject() && config->ignoreDataAddressEquality)); } // The reason we have to do this early scan is as follows @@ -948,9 +948,9 @@ // complicates things for the dynamic linker and means we would have to reserve // space for the extra PT_LOAD even if we end up not using it. template -static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, - uint64_t Offset, Symbol &Sym, const RelTy &Rel, - int64_t Addend) { +static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type, + uint64_t offset, Symbol &sym, const RelTy &rel, + int64_t addend) { // If the relocation is known to be a link-time constant, we know no dynamic // relocation will be created, pass the control to relocateAlloc() or // relocateNonAlloc() to resolve it. @@ -958,23 +958,23 @@ // The behavior of an undefined weak reference is implementation defined. If // the relocation is to a weak undef, and we are producing an executable, let // relocate{,Non}Alloc() resolve it. - if (isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Offset) || - (!Config->Shared && Sym.isUndefWeak())) { - Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + if (isStaticLinkTimeConstant(expr, type, sym, sec, offset) || + (!config->shared && sym.isUndefWeak())) { + sec.relocations.push_back({expr, type, offset, addend, &sym}); return; } - bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText; - if (CanWrite) { - RelType Rel = Target->getDynRel(Type); - if (Expr == R_GOT || (Rel == Target->SymbolicRel && !Sym.IsPreemptible)) { - addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type); + bool canWrite = (sec.flags & SHF_WRITE) || !config->zText; + if (canWrite) { + RelType rel = target->getDynRel(type); + if (expr == R_GOT || (rel == target->symbolicRel && !sym.isPreemptible)) { + addRelativeReloc(&sec, offset, &sym, addend, expr, type); return; - } else if (Rel != 0) { - if (Config->EMachine == EM_MIPS && Rel == Target->SymbolicRel) - Rel = Target->RelativeRel; - Sec.getPartition().RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, - R_ADDEND, Type); + } else if (rel != 0) { + if (config->emachine == EM_MIPS && rel == target->symbolicRel) + rel = target->relativeRel; + sec.getPartition().relaDyn->addReloc(rel, &sec, offset, &sym, addend, + R_ADDEND, type); // MIPS ABI turns using of GOT and dynamic relocations inside out. // While regular ABI uses dynamic relocations to fill up GOT entries @@ -991,19 +991,19 @@ // to the GOT entry and reads the GOT entry when it needs to perform // a dynamic relocation. // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 - if (Config->EMachine == EM_MIPS) - In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); + if (config->emachine == EM_MIPS) + in.mipsGot->addEntry(*sec.file, sym, addend, expr); return; } } - if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) { + if (!canWrite && (config->isPic && !isRelExpr(expr))) { error( - "can't create dynamic relocation " + toString(Type) + " against " + - (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + + "can't create dynamic relocation " + toString(type) + " against " + + (sym.getName().empty() ? "local symbol" : "symbol: " + toString(sym)) + " in readonly segment; recompile object files with -fPIC " "or pass '-Wl,-z,notext' to allow text relocations in the output" + - getLocation(Sec, Sym, Offset)); + getLocation(sec, sym, offset)); return; } @@ -1013,40 +1013,40 @@ // Among R_ABS relocatoin types, SymbolicRel has the same size as the word // size. Others have fewer bits and may cause runtime overflow in -pie/-shared // mode. Disallow them. - if (Config->Shared || - (Config->Pie && Expr == R_ABS && Type != Target->SymbolicRel)) { + if (config->shared || + (config->pie && expr == R_ABS && type != target->symbolicRel)) { errorOrWarn( - "relocation " + toString(Type) + " cannot be used against " + - (Sym.getName().empty() ? "local symbol" : "symbol " + toString(Sym)) + - "; recompile with -fPIC" + getLocation(Sec, Sym, Offset)); + "relocation " + toString(type) + " cannot be used against " + + (sym.getName().empty() ? "local symbol" : "symbol " + toString(sym)) + + "; recompile with -fPIC" + getLocation(sec, sym, offset)); return; } // If the symbol is undefined we already reported any relevant errors. - if (Sym.isUndefined()) + if (sym.isUndefined()) return; - if (!canDefineSymbolInExecutable(Sym)) { - error("cannot preempt symbol: " + toString(Sym) + - getLocation(Sec, Sym, Offset)); + if (!canDefineSymbolInExecutable(sym)) { + error("cannot preempt symbol: " + toString(sym) + + getLocation(sec, sym, offset)); return; } - if (Sym.isObject()) { + if (sym.isObject()) { // Produce a copy relocation. - if (auto *SS = dyn_cast(&Sym)) { - if (!Config->ZCopyreloc) - error("unresolvable relocation " + toString(Type) + - " against symbol '" + toString(*SS) + + if (auto *ss = dyn_cast(&sym)) { + if (!config->zCopyreloc) + error("unresolvable relocation " + toString(type) + + " against symbol '" + toString(*ss) + "'; recompile with -fPIC or remove '-z nocopyreloc'" + - getLocation(Sec, Sym, Offset)); - addCopyRelSymbol(*SS); + getLocation(sec, sym, offset)); + addCopyRelSymbol(*ss); } - Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + sec.relocations.push_back({expr, type, offset, addend, &sym}); return; } - if (Sym.isFunc()) { + if (sym.isFunc()) { // This handles a non PIC program call to function in a shared library. In // an ideal world, we could just report an error saying the relocation can // overflow at runtime. In the real world with glibc, crt1.o has a @@ -1074,65 +1074,65 @@ // compiled without -fPIE/-fPIC and doesn't maintain ebx. // * If a library definition gets preempted to the executable, it will have // the wrong ebx value. - if (Config->Pie && Config->EMachine == EM_386) - errorOrWarn("symbol '" + toString(Sym) + + if (config->pie && config->emachine == EM_386) + errorOrWarn("symbol '" + toString(sym) + "' cannot be preempted; recompile with -fPIE" + - getLocation(Sec, Sym, Offset)); - if (!Sym.isInPlt()) - addPltEntry(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); - if (!Sym.isDefined()) + getLocation(sec, sym, offset)); + if (!sym.isInPlt()) + addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym); + if (!sym.isDefined()) replaceWithDefined( - Sym, In.Plt, - Target->PltHeaderSize + Target->PltEntrySize * Sym.PltIndex, 0); - Sym.NeedsPltAddr = true; - Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); + sym, in.plt, + target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0); + sym.needsPltAddr = true; + sec.relocations.push_back({expr, type, offset, addend, &sym}); return; } - errorOrWarn("symbol '" + toString(Sym) + "' has no type" + - getLocation(Sec, Sym, Offset)); + errorOrWarn("symbol '" + toString(sym) + "' has no type" + + getLocation(sec, sym, offset)); } struct IRelativeReloc { - RelType Type; - InputSectionBase *Sec; - uint64_t Offset; - Symbol *Sym; + RelType type; + InputSectionBase *sec; + uint64_t offset; + Symbol *sym; }; -static std::vector IRelativeRelocs; +static std::vector iRelativeRelocs; template -static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, - RelTy *End) { - const RelTy &Rel = *I; - uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); - Symbol &Sym = Sec.getFile()->getSymbol(SymIndex); - RelType Type; +static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i, + RelTy *end) { + const RelTy &rel = *i; + uint32_t symIndex = rel.getSymbol(config->isMips64EL); + Symbol &sym = sec.getFile()->getSymbol(symIndex); + RelType type; // Deal with MIPS oddity. - if (Config->MipsN32Abi) { - Type = getMipsN32RelType(I, End); + if (config->mipsN32Abi) { + type = getMipsN32RelType(i, end); } else { - Type = Rel.getType(Config->IsMips64EL); - ++I; + type = rel.getType(config->isMips64EL); + ++i; } // Get an offset in an output section this relocation is applied to. - uint64_t Offset = GetOffset.get(Rel.r_offset); - if (Offset == uint64_t(-1)) + uint64_t offset = getOffset.get(rel.r_offset); + if (offset == uint64_t(-1)) return; // Error if the target symbol is undefined. Symbol index 0 may be used by // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them. - if (SymIndex != 0 && maybeReportUndefined(Sym, Sec, Rel.r_offset)) + if (symIndex != 0 && maybeReportUndefined(sym, sec, rel.r_offset)) return; - const uint8_t *RelocatedAddr = Sec.data().begin() + Rel.r_offset; - RelExpr Expr = Target->getRelExpr(Type, Sym, RelocatedAddr); + const uint8_t *relocatedAddr = sec.data().begin() + rel.r_offset; + RelExpr expr = target->getRelExpr(type, sym, relocatedAddr); // Ignore "hint" relocations because they are only markers for relaxation. - if (oneof(Expr)) + if (oneof(expr)) return; // We can separate the small code model relocations into 2 categories: @@ -1143,21 +1143,21 @@ // got-based small code model relocs. The .toc sections get placed after the // end of the linker allocated .got section and we do sort those so sections // addressed with small code model relocations come first. - if (Config->EMachine == EM_PPC64 && isPPC64SmallCodeModelTocReloc(Type)) - Sec.File->PPC64SmallCodeModelTocRelocs = true; + if (config->emachine == EM_PPC64 && isPPC64SmallCodeModelTocReloc(type)) + sec.file->ppc64SmallCodeModelTocRelocs = true; - if (Sym.isGnuIFunc() && !Config->ZText && Config->WarnIfuncTextrel) { + if (sym.isGnuIFunc() && !config->zText && config->warnIfuncTextrel) { warn("using ifunc symbols when text relocations are allowed may produce " "a binary that will segfault, if the object file is linked with " "old version of glibc (glibc 2.28 and earlier). If this applies to " "you, consider recompiling the object files without -fPIC and " "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to " "turn off this warning." + - getLocation(Sec, Sym, Offset)); + getLocation(sec, sym, offset)); } // Read an addend. - int64_t Addend = computeAddend(Rel, End, Sec, Expr, Sym.isLocal()); + int64_t addend = computeAddend(rel, end, sec, expr, sym.isLocal()); // Relax relocations. // @@ -1167,15 +1167,15 @@ // be resolved within the executable will actually be resolved that way at // runtime, because the main exectuable is always at the beginning of a search // list. We can leverage that fact. - if (!Sym.IsPreemptible && (!Sym.isGnuIFunc() || Config->ZIfuncNoplt)) { - if (Expr == R_GOT_PC && !isAbsoluteValue(Sym)) { - Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr); + if (!sym.isPreemptible && (!sym.isGnuIFunc() || config->zIfuncNoplt)) { + if (expr == R_GOT_PC && !isAbsoluteValue(sym)) { + expr = target->adjustRelaxExpr(type, relocatedAddr, expr); } else { // Addend of R_PPC_PLTREL24 is used to choose call stub type. It should be // ignored if optimized to R_PC. - if (Config->EMachine == EM_PPC && Expr == R_PPC32_PLTREL) - Addend = 0; - Expr = fromPlt(Expr); + if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL) + addend = 0; + expr = fromPlt(expr); } } @@ -1183,39 +1183,39 @@ // uses their addresses, we need GOT or GOTPLT to be created. // // The 4 types that relative GOTPLT are all x86 and x86-64 specific. - if (oneof(Expr)) { - In.GotPlt->HasGotPltOffRel = true; + if (oneof(expr)) { + in.gotPlt->hasGotPltOffRel = true; } else if (oneof( - Expr)) { - In.Got->HasGotOffRel = true; + expr)) { + in.got->hasGotOffRel = true; } // Process some TLS relocations, including relaxing TLS relocations. // Note that this function does not handle all TLS relocations. - if (unsigned Processed = - handleTlsRelocation(Type, Sym, Sec, Offset, Addend, Expr)) { - I += (Processed - 1); + if (unsigned processed = + handleTlsRelocation(type, sym, sec, offset, addend, expr)) { + i += (processed - 1); return; } // We were asked not to generate PLT entries for ifuncs. Instead, pass the // direct relocation on through. - if (Sym.isGnuIFunc() && Config->ZIfuncNoplt) { - Sym.ExportDynamic = true; - Main->RelaDyn->addReloc(Type, &Sec, Offset, &Sym, Addend, R_ADDEND, Type); + if (sym.isGnuIFunc() && config->zIfuncNoplt) { + sym.exportDynamic = true; + mainPart->relaDyn->addReloc(type, &sec, offset, &sym, addend, R_ADDEND, type); return; } // Non-preemptible ifuncs require special handling. First, handle the usual // case where the symbol isn't one of these. - if (!Sym.isGnuIFunc() || Sym.IsPreemptible) { + if (!sym.isGnuIFunc() || sym.isPreemptible) { // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. - if (needsPlt(Expr) && !Sym.isInPlt()) - addPltEntry(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); + if (needsPlt(expr) && !sym.isInPlt()) + addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym); // Create a GOT slot if a relocation needs GOT. - if (needsGot(Expr)) { - if (Config->EMachine == EM_MIPS) { + if (needsGot(expr)) { + if (config->emachine == EM_MIPS) { // MIPS ABI has special rules to process GOT entries and doesn't // require relocation entries for them. A special case is TLS // relocations. In that case dynamic loader applies dynamic @@ -1223,9 +1223,9 @@ // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); - } else if (!Sym.isInGot()) { - addGotEntry(Sym); + in.mipsGot->addEntry(*sec.file, sym, addend, expr); + } else if (!sym.isInGot()) { + addGotEntry(sym); } } } else { @@ -1275,9 +1275,9 @@ // the exact same way as a GOT entry, so we can avoid needing to make the // PLT entry canonical by translating such relocations into IRELATIVE // relocations in the RelaIplt. - if (!Sym.isInPlt()) { + if (!sym.isInPlt()) { // Create PLT and GOTPLT slots for the symbol. - Sym.IsInIplt = true; + sym.isInIplt = true; // Create a copy of the symbol to use as the target of the IRELATIVE // relocation in the IgotPlt. This is in case we make the PLT canonical @@ -1286,12 +1286,12 @@ // FIXME: Creating a copy of the symbol here is a bit of a hack. All // that's really needed to create the IRELATIVE is the section and value, // so ideally we should just need to copy those. - auto *DirectSym = make(cast(Sym)); - addPltEntry(In.Iplt, In.IgotPlt, In.RelaIplt, Target->IRelativeRel, - *DirectSym); - Sym.PltIndex = DirectSym->PltIndex; + auto *directSym = make(cast(sym)); + addPltEntry(in.iplt, in.igotPlt, in.relaIplt, target->iRelativeRel, + *directSym); + sym.pltIndex = directSym->pltIndex; } - if (Expr == R_ABS && Addend == 0 && (Sec.Flags & SHF_WRITE)) { + if (expr == R_ABS && addend == 0 && (sec.flags & SHF_WRITE)) { // We might be able to represent this as an IRELATIVE. But we don't know // yet whether some later relocation will make the symbol point to a // canonical PLT, which would make this either a dynamic RELATIVE (PIC) or @@ -1299,32 +1299,32 @@ // required to process the relocation, and after scanRelocs() has been // called on all relocations, the relocation is resolved by // addIRelativeRelocs(). - IRelativeRelocs.push_back({Type, &Sec, Offset, &Sym}); + iRelativeRelocs.push_back({type, &sec, offset, &sym}); return; } - if (needsGot(Expr)) { + if (needsGot(expr)) { // Redirect GOT accesses to point to the Igot. // // This field is also used to keep track of whether we ever needed a GOT // entry. If we did and we make the PLT canonical later, we'll need to // create a GOT entry pointing to the PLT entry for Sym. - Sym.GotInIgot = true; - } else if (!needsPlt(Expr)) { + sym.gotInIgot = true; + } else if (!needsPlt(expr)) { // Make the ifunc's PLT entry canonical by changing the value of its // symbol to redirect all references to point to it. - unsigned EntryOffset = Sym.PltIndex * Target->PltEntrySize; - if (Config->ZRetpolineplt) - EntryOffset += Target->PltHeaderSize; - - auto &D = cast(Sym); - D.Section = In.Iplt; - D.Value = EntryOffset; - D.Size = 0; + unsigned entryOffset = sym.pltIndex * target->pltEntrySize; + if (config->zRetpolineplt) + entryOffset += target->pltHeaderSize; + + auto &d = cast(sym); + d.section = in.iplt; + d.value = entryOffset; + d.size = 0; // It's important to set the symbol type here so that dynamic loaders // don't try to call the PLT as if it were an ifunc resolver. - D.Type = STT_FUNC; + d.type = STT_FUNC; - if (Sym.GotInIgot) { + if (sym.gotInIgot) { // We previously encountered a GOT generating reference that we // redirected to the Igot. Now that the PLT entry is canonical we must // clear the redirection to the Igot and add a GOT entry. As we've @@ -1333,74 +1333,74 @@ // // We don't need to worry about creating a MIPS GOT here because ifuncs // aren't a thing on MIPS. - Sym.GotInIgot = false; - addGotEntry(Sym); + sym.gotInIgot = false; + addGotEntry(sym); } } } - processRelocAux(Sec, Expr, Type, Offset, Sym, Rel, Addend); + processRelocAux(sec, expr, type, offset, sym, rel, addend); } template -static void scanRelocs(InputSectionBase &Sec, ArrayRef Rels) { - OffsetGetter GetOffset(Sec); +static void scanRelocs(InputSectionBase &sec, ArrayRef rels) { + OffsetGetter getOffset(sec); // Not all relocations end up in Sec.Relocations, but a lot do. - Sec.Relocations.reserve(Rels.size()); + sec.relocations.reserve(rels.size()); - for (auto I = Rels.begin(), End = Rels.end(); I != End;) - scanReloc(Sec, GetOffset, I, End); + for (auto i = rels.begin(), end = rels.end(); i != end;) + scanReloc(sec, getOffset, i, end); // Sort relocations by offset for more efficient searching for // R_RISCV_PCREL_HI20 and R_PPC64_ADDR64. - if (Config->EMachine == EM_RISCV || - (Config->EMachine == EM_PPC64 && Sec.Name == ".toc")) - llvm::stable_sort(Sec.Relocations, - [](const Relocation &LHS, const Relocation &RHS) { - return LHS.Offset < RHS.Offset; + if (config->emachine == EM_RISCV || + (config->emachine == EM_PPC64 && sec.name == ".toc")) + llvm::stable_sort(sec.relocations, + [](const Relocation &lhs, const Relocation &rhs) { + return lhs.offset < rhs.offset; }); } -template void elf::scanRelocations(InputSectionBase &S) { - if (S.AreRelocsRela) - scanRelocs(S, S.relas()); +template void elf::scanRelocations(InputSectionBase &s) { + if (s.areRelocsRela) + scanRelocs(s, s.relas()); else - scanRelocs(S, S.rels()); + scanRelocs(s, s.rels()); } // Figure out which representation to use for any absolute relocs to // non-preemptible ifuncs that we visited during scanRelocs(). void elf::addIRelativeRelocs() { - for (IRelativeReloc &R : IRelativeRelocs) { - if (R.Sym->Type == STT_GNU_IFUNC) - In.RelaIplt->addReloc( - {Target->IRelativeRel, R.Sec, R.Offset, true, R.Sym, 0}); - else if (Config->Pic) - addRelativeReloc(R.Sec, R.Offset, R.Sym, 0, R_ABS, R.Type); + for (IRelativeReloc &r : iRelativeRelocs) { + if (r.sym->type == STT_GNU_IFUNC) + in.relaIplt->addReloc( + {target->iRelativeRel, r.sec, r.offset, true, r.sym, 0}); + else if (config->isPic) + addRelativeReloc(r.sec, r.offset, r.sym, 0, R_ABS, r.type); else - R.Sec->Relocations.push_back({R_ABS, R.Type, R.Offset, 0, R.Sym}); + r.sec->relocations.push_back({R_ABS, r.type, r.offset, 0, r.sym}); } - IRelativeRelocs.clear(); + iRelativeRelocs.clear(); } -static bool mergeCmp(const InputSection *A, const InputSection *B) { +static bool mergeCmp(const InputSection *a, const InputSection *b) { // std::merge requires a strict weak ordering. - if (A->OutSecOff < B->OutSecOff) + if (a->outSecOff < b->outSecOff) return true; - if (A->OutSecOff == B->OutSecOff) { - auto *TA = dyn_cast(A); - auto *TB = dyn_cast(B); + if (a->outSecOff == b->outSecOff) { + auto *ta = dyn_cast(a); + auto *tb = dyn_cast(b); // Check if Thunk is immediately before any specific Target // InputSection for example Mips LA25 Thunks. - if (TA && TA->getTargetInputSection() == B) + if (ta && ta->getTargetInputSection() == b) return true; // Place Thunk Sections without specific targets before // non-Thunk Sections. - if (TA && !TB && !TA->getTargetInputSection()) + if (ta && !tb && !ta->getTargetInputSection()) return true; } @@ -1410,14 +1410,14 @@ // Call Fn on every executable InputSection accessed via the linker script // InputSectionDescription::Sections. static void forEachInputSectionDescription( - ArrayRef OutputSections, - llvm::function_ref Fn) { - for (OutputSection *OS : OutputSections) { - if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) + ArrayRef outputSections, + llvm::function_ref fn) { + for (OutputSection *os : outputSections) { + if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR)) continue; - for (BaseCommand *BC : OS->SectionCommands) - if (auto *ISD = dyn_cast(BC)) - Fn(OS, ISD); + for (BaseCommand *bc : os->sectionCommands) + if (auto *isd = dyn_cast(bc)) + fn(os, isd); } } @@ -1512,54 +1512,54 @@ // in the Sections vector, and recalculate the InputSection output section // offsets. // This may invalidate any output section offsets stored outside of InputSection -void ThunkCreator::mergeThunks(ArrayRef OutputSections) { +void ThunkCreator::mergeThunks(ArrayRef outputSections) { forEachInputSectionDescription( - OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { - if (ISD->ThunkSections.empty()) + outputSections, [&](OutputSection *os, InputSectionDescription *isd) { + if (isd->thunkSections.empty()) return; // Remove any zero sized precreated Thunks. - llvm::erase_if(ISD->ThunkSections, - [](const std::pair &TS) { - return TS.first->getSize() == 0; + llvm::erase_if(isd->thunkSections, + [](const std::pair &ts) { + return ts.first->getSize() == 0; }); // ISD->ThunkSections contains all created ThunkSections, including // those inserted in previous passes. Extract the Thunks created this // pass and order them in ascending OutSecOff. - std::vector NewThunks; - for (const std::pair TS : ISD->ThunkSections) - if (TS.second == Pass) - NewThunks.push_back(TS.first); - llvm::stable_sort(NewThunks, - [](const ThunkSection *A, const ThunkSection *B) { - return A->OutSecOff < B->OutSecOff; + std::vector newThunks; + for (const std::pair ts : isd->thunkSections) + if (ts.second == pass) + newThunks.push_back(ts.first); + llvm::stable_sort(newThunks, + [](const ThunkSection *a, const ThunkSection *b) { + return a->outSecOff < b->outSecOff; }); // Merge sorted vectors of Thunks and InputSections by OutSecOff - std::vector Tmp; - Tmp.reserve(ISD->Sections.size() + NewThunks.size()); + std::vector tmp; + tmp.reserve(isd->sections.size() + newThunks.size()); - std::merge(ISD->Sections.begin(), ISD->Sections.end(), - NewThunks.begin(), NewThunks.end(), std::back_inserter(Tmp), + std::merge(isd->sections.begin(), isd->sections.end(), + newThunks.begin(), newThunks.end(), std::back_inserter(tmp), mergeCmp); - ISD->Sections = std::move(Tmp); + isd->sections = std::move(tmp); }); } // Find or create a ThunkSection within the InputSectionDescription (ISD) that // is in range of Src. An ISD maps to a range of InputSections described by a // linker script section pattern such as { .text .text.* }. -ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS, - InputSectionDescription *ISD, - uint32_t Type, uint64_t Src) { - for (std::pair TP : ISD->ThunkSections) { - ThunkSection *TS = TP.first; - uint64_t TSBase = OS->Addr + TS->OutSecOff; - uint64_t TSLimit = TSBase + TS->getSize(); - if (Target->inBranchRange(Type, Src, (Src > TSLimit) ? TSBase : TSLimit)) - return TS; +ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *os, InputSection *isec, + InputSectionDescription *isd, + uint32_t type, uint64_t src) { + for (std::pair tp : isd->thunkSections) { + ThunkSection *ts = tp.first; + uint64_t tsBase = os->addr + ts->outSecOff; + uint64_t tsLimit = tsBase + ts->getSize(); + if (target->inBranchRange(type, src, (src > tsLimit) ? tsBase : tsLimit)) + return ts; } // No suitable ThunkSection exists. This can happen when there is a branch @@ -1567,40 +1567,40 @@ // many Thunks. Create a new ThunkSection as close to the InputSection as // possible. Error if InputSection is so large we cannot place ThunkSection // anywhere in Range. - uint64_t ThunkSecOff = IS->OutSecOff; - if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) { - ThunkSecOff = IS->OutSecOff + IS->getSize(); - if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) + uint64_t thunkSecOff = isec->outSecOff; + if (!target->inBranchRange(type, src, os->addr + thunkSecOff)) { + thunkSecOff = isec->outSecOff + isec->getSize(); + if (!target->inBranchRange(type, src, os->addr + thunkSecOff)) fatal("InputSection too large for range extension thunk " + - IS->getObjMsg(Src - (OS->Addr + IS->OutSecOff))); + isec->getObjMsg(src - (os->addr + isec->outSecOff))); } - return addThunkSection(OS, ISD, ThunkSecOff); + return addThunkSection(os, isd, thunkSecOff); } // Add a Thunk that needs to be placed in a ThunkSection that immediately // precedes its Target. -ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { - ThunkSection *TS = ThunkedSections.lookup(IS); - if (TS) - return TS; +ThunkSection *ThunkCreator::getISThunkSec(InputSection *isec) { + ThunkSection *ts = thunkedSections.lookup(isec); + if (ts) + return ts; // Find InputSectionRange within Target Output Section (TOS) that the // InputSection (IS) that we need to precede is in. - OutputSection *TOS = IS->getParent(); - for (BaseCommand *BC : TOS->SectionCommands) { - auto *ISD = dyn_cast(BC); - if (!ISD || ISD->Sections.empty()) + OutputSection *tos = isec->getParent(); + for (BaseCommand *bc : tos->sectionCommands) { + auto *isd = dyn_cast(bc); + if (!isd || isd->sections.empty()) continue; - InputSection *First = ISD->Sections.front(); - InputSection *Last = ISD->Sections.back(); + InputSection *first = isd->sections.front(); + InputSection *last = isd->sections.back(); - if (IS->OutSecOff < First->OutSecOff || Last->OutSecOff < IS->OutSecOff) + if (isec->outSecOff < first->outSecOff || last->outSecOff < isec->outSecOff) continue; - TS = addThunkSection(TOS, ISD, IS->OutSecOff); - ThunkedSections[IS] = TS; - return TS; + ts = addThunkSection(tos, isd, isec->outSecOff); + thunkedSections[isec] = ts; + return ts; } return nullptr; @@ -1623,93 +1623,93 @@ // distance from a thunk to its target will be sufficiently small to // allow for the creation of a short thunk. void ThunkCreator::createInitialThunkSections( - ArrayRef OutputSections) { - uint32_t ThunkSectionSpacing = Target->getThunkSectionSpacing(); + ArrayRef outputSections) { + uint32_t thunkSectionSpacing = target->getThunkSectionSpacing(); forEachInputSectionDescription( - OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { - if (ISD->Sections.empty()) + outputSections, [&](OutputSection *os, InputSectionDescription *isd) { + if (isd->sections.empty()) return; - uint32_t ISDBegin = ISD->Sections.front()->OutSecOff; - uint32_t ISDEnd = - ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize(); - uint32_t LastThunkLowerBound = -1; - if (ISDEnd - ISDBegin > ThunkSectionSpacing * 2) - LastThunkLowerBound = ISDEnd - ThunkSectionSpacing; - - uint32_t ISLimit; - uint32_t PrevISLimit = ISDBegin; - uint32_t ThunkUpperBound = ISDBegin + ThunkSectionSpacing; - - for (const InputSection *IS : ISD->Sections) { - ISLimit = IS->OutSecOff + IS->getSize(); - if (ISLimit > ThunkUpperBound) { - addThunkSection(OS, ISD, PrevISLimit); - ThunkUpperBound = PrevISLimit + ThunkSectionSpacing; + uint32_t isdBegin = isd->sections.front()->outSecOff; + uint32_t isdEnd = + isd->sections.back()->outSecOff + isd->sections.back()->getSize(); + uint32_t lastThunkLowerBound = -1; + if (isdEnd - isdBegin > thunkSectionSpacing * 2) + lastThunkLowerBound = isdEnd - thunkSectionSpacing; + + uint32_t isecLimit; + uint32_t prevISLimit = isdBegin; + uint32_t thunkUpperBound = isdBegin + thunkSectionSpacing; + + for (const InputSection *isec : isd->sections) { + isecLimit = isec->outSecOff + isec->getSize(); + if (isecLimit > thunkUpperBound) { + addThunkSection(os, isd, prevISLimit); + thunkUpperBound = prevISLimit + thunkSectionSpacing; } - if (ISLimit > LastThunkLowerBound) + if (isecLimit > lastThunkLowerBound) break; - PrevISLimit = ISLimit; + prevISLimit = isecLimit; } - addThunkSection(OS, ISD, ISLimit); + addThunkSection(os, isd, isecLimit); }); } -ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, - InputSectionDescription *ISD, - uint64_t Off) { - auto *TS = make(OS, Off); - TS->Partition = OS->Partition; - ISD->ThunkSections.push_back({TS, Pass}); - return TS; +ThunkSection *ThunkCreator::addThunkSection(OutputSection *os, + InputSectionDescription *isd, + uint64_t off) { + auto *ts = make(os, off); + ts->partition = os->partition; + isd->thunkSections.push_back({ts, pass}); + return ts; } -static bool isThunkSectionCompatible(InputSection *Source, - SectionBase *Target) { +static bool isThunkSectionCompatible(InputSection *source, + SectionBase *target) { // We can't reuse thunks in different loadable partitions because they might // not be loaded. But partition 1 (the main partition) will always be loaded. - if (Source->Partition != Target->Partition) - return Target->Partition == 1; + if (source->partition != target->partition) + return target->partition == 1; return true; } -std::pair ThunkCreator::getThunk(InputSection *IS, - Relocation &Rel, uint64_t Src) { - std::vector *ThunkVec = nullptr; +std::pair ThunkCreator::getThunk(InputSection *isec, + Relocation &rel, uint64_t src) { + std::vector *thunkVec = nullptr; // We use (section, offset) pair to find the thunk position if possible so // that we create only one thunk for aliased symbols or ICFed sections. - if (auto *D = dyn_cast(Rel.Sym)) - if (!D->isInPlt() && D->Section) - ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}]; - if (!ThunkVec) - ThunkVec = &ThunkedSymbols[Rel.Sym]; + if (auto *d = dyn_cast(rel.sym)) + if (!d->isInPlt() && d->section) + thunkVec = &thunkedSymbolsBySection[{d->section->repl, d->value}]; + if (!thunkVec) + thunkVec = &thunkedSymbols[rel.sym]; // Check existing Thunks for Sym to see if they can be reused - for (Thunk *T : *ThunkVec) - if (isThunkSectionCompatible(IS, T->getThunkTargetSym()->Section) && - T->isCompatibleWith(*IS, Rel) && - Target->inBranchRange(Rel.Type, Src, T->getThunkTargetSym()->getVA())) - return std::make_pair(T, false); + for (Thunk *t : *thunkVec) + if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) && + t->isCompatibleWith(*isec, rel) && + target->inBranchRange(rel.type, src, t->getThunkTargetSym()->getVA())) + return std::make_pair(t, false); // No existing compatible Thunk in range, create a new one - Thunk *T = addThunk(*IS, Rel); - ThunkVec->push_back(T); - return std::make_pair(T, true); + Thunk *t = addThunk(*isec, rel); + thunkVec->push_back(t); + return std::make_pair(t, true); } // Return true if the relocation target is an in range Thunk. // Return false if the relocation is not to a Thunk. If the relocation target // was originally to a Thunk, but is no longer in range we revert the // relocation back to its original non-Thunk target. -bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { - if (Thunk *T = Thunks.lookup(Rel.Sym)) { - if (Target->inBranchRange(Rel.Type, Src, Rel.Sym->getVA())) +bool ThunkCreator::normalizeExistingThunk(Relocation &rel, uint64_t src) { + if (Thunk *t = thunks.lookup(rel.sym)) { + if (target->inBranchRange(rel.type, src, rel.sym->getVA())) return true; - Rel.Sym = &T->Destination; - if (Rel.Sym->isInPlt()) - Rel.Expr = toPlt(Rel.Expr); + rel.sym = &t->destination; + if (rel.sym->isInPlt()) + rel.expr = toPlt(rel.expr); } return false; } @@ -1739,15 +1739,15 @@ // made no changes. If the target requires range extension thunks, currently // ARM, then any future change in offset between caller and callee risks a // relocation out of range error. -bool ThunkCreator::createThunks(ArrayRef OutputSections) { - bool AddressesChanged = false; +bool ThunkCreator::createThunks(ArrayRef outputSections) { + bool addressesChanged = false; - if (Pass == 0 && Target->getThunkSectionSpacing()) - createInitialThunkSections(OutputSections); + if (pass == 0 && target->getThunkSectionSpacing()) + createInitialThunkSections(outputSections); // With Thunk Size much smaller than branch range we expect to // converge quickly; if we get to 10 something has gone wrong. - if (Pass == 10) + if (pass == 10) fatal("thunk creation not converged"); // Create all the Thunks and insert them into synthetic ThunkSections. The @@ -1756,57 +1756,57 @@ // ThunkSections as ThunkSections are not always inserted into the same // InputSectionDescription as the caller. forEachInputSectionDescription( - OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { - for (InputSection *IS : ISD->Sections) - for (Relocation &Rel : IS->Relocations) { - uint64_t Src = IS->getVA(Rel.Offset); + outputSections, [&](OutputSection *os, InputSectionDescription *isd) { + for (InputSection *isec : isd->sections) + for (Relocation &rel : isec->relocations) { + uint64_t src = isec->getVA(rel.offset); // If we are a relocation to an existing Thunk, check if it is // still in range. If not then Rel will be altered to point to its // original target so another Thunk can be generated. - if (Pass > 0 && normalizeExistingThunk(Rel, Src)) + if (pass > 0 && normalizeExistingThunk(rel, src)) continue; - if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src, - *Rel.Sym)) + if (!target->needsThunk(rel.expr, rel.type, isec->file, src, + *rel.sym)) continue; - Thunk *T; - bool IsNew; - std::tie(T, IsNew) = getThunk(IS, Rel, Src); + Thunk *t; + bool isNew; + std::tie(t, isNew) = getThunk(isec, rel, src); - if (IsNew) { + if (isNew) { // Find or create a ThunkSection for the new Thunk - ThunkSection *TS; - if (auto *TIS = T->getTargetInputSection()) - TS = getISThunkSec(TIS); + ThunkSection *ts; + if (auto *tis = t->getTargetInputSection()) + ts = getISThunkSec(tis); else - TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src); - TS->addThunk(T); - Thunks[T->getThunkTargetSym()] = T; + ts = getISDThunkSec(os, isec, isd, rel.type, src); + ts->addThunk(t); + thunks[t->getThunkTargetSym()] = t; } // Redirect relocation to Thunk, we never go via the PLT to a Thunk - Rel.Sym = T->getThunkTargetSym(); - Rel.Expr = fromPlt(Rel.Expr); + rel.sym = t->getThunkTargetSym(); + rel.expr = fromPlt(rel.expr); // The addend of R_PPC_PLTREL24 should be ignored after changing to // R_PC. - if (Config->EMachine == EM_PPC && Rel.Type == R_PPC_PLTREL24) - Rel.Addend = 0; + if (config->emachine == EM_PPC && rel.type == R_PPC_PLTREL24) + rel.addend = 0; } - for (auto &P : ISD->ThunkSections) - AddressesChanged |= P.first->assignOffsets(); + for (auto &p : isd->thunkSections) + addressesChanged |= p.first->assignOffsets(); }); - for (auto &P : ThunkedSections) - AddressesChanged |= P.second->assignOffsets(); + for (auto &p : thunkedSections) + addressesChanged |= p.second->assignOffsets(); // Merge all created synthetic ThunkSections back into OutputSection - mergeThunks(OutputSections); - ++Pass; - return AddressesChanged; + mergeThunks(outputSections); + ++pass; + return addressesChanged; } template void elf::scanRelocations(InputSectionBase &); Index: lld/trunk/ELF/ScriptLexer.h =================================================================== --- lld/trunk/ELF/ScriptLexer.h +++ lld/trunk/ELF/ScriptLexer.h @@ -20,25 +20,25 @@ class ScriptLexer { public: - explicit ScriptLexer(MemoryBufferRef MB); + explicit ScriptLexer(MemoryBufferRef mb); - void setError(const Twine &Msg); - void tokenize(MemoryBufferRef MB); - static StringRef skipSpace(StringRef S); + void setError(const Twine &msg); + void tokenize(MemoryBufferRef mb); + static StringRef skipSpace(StringRef s); bool atEOF(); StringRef next(); StringRef peek(); StringRef peek2(); void skip(); - bool consume(StringRef Tok); - void expect(StringRef Expect); - bool consumeLabel(StringRef Tok); + bool consume(StringRef tok); + void expect(StringRef expect); + bool consumeLabel(StringRef tok); std::string getCurrentLocation(); - std::vector MBs; - std::vector Tokens; - bool InExpr = false; - size_t Pos = 0; + std::vector mbs; + std::vector tokens; + bool inExpr = false; + size_t pos = 0; private: void maybeSplitExpr(); Index: lld/trunk/ELF/ScriptLexer.cpp =================================================================== --- lld/trunk/ELF/ScriptLexer.cpp +++ lld/trunk/ELF/ScriptLexer.cpp @@ -41,169 +41,169 @@ // Returns a whole line containing the current token. StringRef ScriptLexer::getLine() { - StringRef S = getCurrentMB().getBuffer(); - StringRef Tok = Tokens[Pos - 1]; + StringRef s = getCurrentMB().getBuffer(); + StringRef tok = tokens[pos - 1]; - size_t Pos = S.rfind('\n', Tok.data() - S.data()); - if (Pos != StringRef::npos) - S = S.substr(Pos + 1); - return S.substr(0, S.find_first_of("\r\n")); + size_t pos = s.rfind('\n', tok.data() - s.data()); + if (pos != StringRef::npos) + s = s.substr(pos + 1); + return s.substr(0, s.find_first_of("\r\n")); } // Returns 1-based line number of the current token. size_t ScriptLexer::getLineNumber() { - StringRef S = getCurrentMB().getBuffer(); - StringRef Tok = Tokens[Pos - 1]; - return S.substr(0, Tok.data() - S.data()).count('\n') + 1; + StringRef s = getCurrentMB().getBuffer(); + StringRef tok = tokens[pos - 1]; + return s.substr(0, tok.data() - s.data()).count('\n') + 1; } // Returns 0-based column number of the current token. size_t ScriptLexer::getColumnNumber() { - StringRef Tok = Tokens[Pos - 1]; - return Tok.data() - getLine().data(); + StringRef tok = tokens[pos - 1]; + return tok.data() - getLine().data(); } std::string ScriptLexer::getCurrentLocation() { - std::string Filename = getCurrentMB().getBufferIdentifier(); - return (Filename + ":" + Twine(getLineNumber())).str(); + std::string filename = getCurrentMB().getBufferIdentifier(); + return (filename + ":" + Twine(getLineNumber())).str(); } -ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); } +ScriptLexer::ScriptLexer(MemoryBufferRef mb) { tokenize(mb); } // We don't want to record cascading errors. Keep only the first one. -void ScriptLexer::setError(const Twine &Msg) { +void ScriptLexer::setError(const Twine &msg) { if (errorCount()) return; - std::string S = (getCurrentLocation() + ": " + Msg).str(); - if (Pos) - S += "\n>>> " + getLine().str() + "\n>>> " + + std::string s = (getCurrentLocation() + ": " + msg).str(); + if (pos) + s += "\n>>> " + getLine().str() + "\n>>> " + std::string(getColumnNumber(), ' ') + "^"; - error(S); + error(s); } // Split S into linker script tokens. -void ScriptLexer::tokenize(MemoryBufferRef MB) { - std::vector Vec; - MBs.push_back(MB); - StringRef S = MB.getBuffer(); - StringRef Begin = S; +void ScriptLexer::tokenize(MemoryBufferRef mb) { + std::vector vec; + mbs.push_back(mb); + StringRef s = mb.getBuffer(); + StringRef begin = s; for (;;) { - S = skipSpace(S); - if (S.empty()) + s = skipSpace(s); + if (s.empty()) break; // Quoted token. Note that double-quote characters are parts of a token // because, in a glob match context, only unquoted tokens are interpreted // as glob patterns. Double-quoted tokens are literal patterns in that // context. - if (S.startswith("\"")) { - size_t E = S.find("\"", 1); - if (E == StringRef::npos) { - StringRef Filename = MB.getBufferIdentifier(); - size_t Lineno = Begin.substr(0, S.data() - Begin.data()).count('\n'); - error(Filename + ":" + Twine(Lineno + 1) + ": unclosed quote"); + if (s.startswith("\"")) { + size_t e = s.find("\"", 1); + if (e == StringRef::npos) { + StringRef filename = mb.getBufferIdentifier(); + size_t lineno = begin.substr(0, s.data() - begin.data()).count('\n'); + error(filename + ":" + Twine(lineno + 1) + ": unclosed quote"); return; } - Vec.push_back(S.take_front(E + 1)); - S = S.substr(E + 1); + vec.push_back(s.take_front(e + 1)); + s = s.substr(e + 1); continue; } // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>". // "|", "||", "&" and "&&" are different operators. - if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") || - S.startswith(">=") || S.startswith("||") || S.startswith("&&")) { - Vec.push_back(S.substr(0, 2)); - S = S.substr(2); + if (s.startswith("<<") || s.startswith("<=") || s.startswith(">>") || + s.startswith(">=") || s.startswith("||") || s.startswith("&&")) { + vec.push_back(s.substr(0, 2)); + s = s.substr(2); continue; } // Unquoted token. This is more relaxed than tokens in C-like language, // so that you can write "file-name.cpp" as one bare token, for example. - size_t Pos = S.find_first_not_of( + size_t pos = s.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "0123456789_.$/\\~=+[]*?-!^:"); // A character that cannot start a word (which is usually a // punctuation) forms a single character token. - if (Pos == 0) - Pos = 1; - Vec.push_back(S.substr(0, Pos)); - S = S.substr(Pos); + if (pos == 0) + pos = 1; + vec.push_back(s.substr(0, pos)); + s = s.substr(pos); } - Tokens.insert(Tokens.begin() + Pos, Vec.begin(), Vec.end()); + tokens.insert(tokens.begin() + pos, vec.begin(), vec.end()); } // Skip leading whitespace characters or comments. -StringRef ScriptLexer::skipSpace(StringRef S) { +StringRef ScriptLexer::skipSpace(StringRef s) { for (;;) { - if (S.startswith("/*")) { - size_t E = S.find("*/", 2); - if (E == StringRef::npos) { + if (s.startswith("/*")) { + size_t e = s.find("*/", 2); + if (e == StringRef::npos) { error("unclosed comment in a linker script"); return ""; } - S = S.substr(E + 2); + s = s.substr(e + 2); continue; } - if (S.startswith("#")) { - size_t E = S.find('\n', 1); - if (E == StringRef::npos) - E = S.size() - 1; - S = S.substr(E + 1); + if (s.startswith("#")) { + size_t e = s.find('\n', 1); + if (e == StringRef::npos) + e = s.size() - 1; + s = s.substr(e + 1); continue; } - size_t Size = S.size(); - S = S.ltrim(); - if (S.size() == Size) - return S; + size_t size = s.size(); + s = s.ltrim(); + if (s.size() == size) + return s; } } // An erroneous token is handled as if it were the last token before EOF. -bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; } +bool ScriptLexer::atEOF() { return errorCount() || tokens.size() == pos; } // Split a given string as an expression. // This function returns "3", "*" and "5" for "3*5" for example. -static std::vector tokenizeExpr(StringRef S) { - StringRef Ops = "+-*/:!~=<>"; // List of operators +static std::vector tokenizeExpr(StringRef s) { + StringRef ops = "+-*/:!~=<>"; // List of operators // Quoted strings are literal strings, so we don't want to split it. - if (S.startswith("\"")) - return {S}; + if (s.startswith("\"")) + return {s}; // Split S with operators as separators. - std::vector Ret; - while (!S.empty()) { - size_t E = S.find_first_of(Ops); + std::vector ret; + while (!s.empty()) { + size_t e = s.find_first_of(ops); // No need to split if there is no operator. - if (E == StringRef::npos) { - Ret.push_back(S); + if (e == StringRef::npos) { + ret.push_back(s); break; } // Get a token before the opreator. - if (E != 0) - Ret.push_back(S.substr(0, E)); + if (e != 0) + ret.push_back(s.substr(0, e)); // Get the operator as a token. // Keep !=, ==, >=, <=, << and >> operators as a single tokens. - if (S.substr(E).startswith("!=") || S.substr(E).startswith("==") || - S.substr(E).startswith(">=") || S.substr(E).startswith("<=") || - S.substr(E).startswith("<<") || S.substr(E).startswith(">>")) { - Ret.push_back(S.substr(E, 2)); - S = S.substr(E + 2); + if (s.substr(e).startswith("!=") || s.substr(e).startswith("==") || + s.substr(e).startswith(">=") || s.substr(e).startswith("<=") || + s.substr(e).startswith("<<") || s.substr(e).startswith(">>")) { + ret.push_back(s.substr(e, 2)); + s = s.substr(e + 2); } else { - Ret.push_back(S.substr(E, 1)); - S = S.substr(E + 1); + ret.push_back(s.substr(e, 1)); + s = s.substr(e + 1); } } - return Ret; + return ret; } // In contexts where expressions are expected, the lexer should apply @@ -216,14 +216,14 @@ // // This function may split the current token into multiple tokens. void ScriptLexer::maybeSplitExpr() { - if (!InExpr || errorCount() || atEOF()) + if (!inExpr || errorCount() || atEOF()) return; - std::vector V = tokenizeExpr(Tokens[Pos]); - if (V.size() == 1) + std::vector v = tokenizeExpr(tokens[pos]); + if (v.size() == 1) return; - Tokens.erase(Tokens.begin() + Pos); - Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end()); + tokens.erase(tokens.begin() + pos); + tokens.insert(tokens.begin() + pos, v.begin(), v.end()); } StringRef ScriptLexer::next() { @@ -235,28 +235,28 @@ setError("unexpected EOF"); return ""; } - return Tokens[Pos++]; + return tokens[pos++]; } StringRef ScriptLexer::peek() { - StringRef Tok = next(); + StringRef tok = next(); if (errorCount()) return ""; - Pos = Pos - 1; - return Tok; + pos = pos - 1; + return tok; } StringRef ScriptLexer::peek2() { skip(); - StringRef Tok = next(); + StringRef tok = next(); if (errorCount()) return ""; - Pos = Pos - 2; - return Tok; + pos = pos - 2; + return tok; } -bool ScriptLexer::consume(StringRef Tok) { - if (peek() == Tok) { +bool ScriptLexer::consume(StringRef tok) { + if (peek() == tok) { skip(); return true; } @@ -264,12 +264,12 @@ } // Consumes Tok followed by ":". Space is allowed between Tok and ":". -bool ScriptLexer::consumeLabel(StringRef Tok) { - if (consume((Tok + ":").str())) +bool ScriptLexer::consumeLabel(StringRef tok) { + if (consume((tok + ":").str())) return true; - if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok && - Tokens[Pos + 1] == ":") { - Pos += 2; + if (tokens.size() >= pos + 2 && tokens[pos] == tok && + tokens[pos + 1] == ":") { + pos += 2; return true; } return false; @@ -277,24 +277,24 @@ void ScriptLexer::skip() { (void)next(); } -void ScriptLexer::expect(StringRef Expect) { +void ScriptLexer::expect(StringRef expect) { if (errorCount()) return; - StringRef Tok = next(); - if (Tok != Expect) - setError(Expect + " expected, but got " + Tok); + StringRef tok = next(); + if (tok != expect) + setError(expect + " expected, but got " + tok); } // Returns true if S encloses T. -static bool encloses(StringRef S, StringRef T) { - return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end(); +static bool encloses(StringRef s, StringRef t) { + return s.bytes_begin() <= t.bytes_begin() && t.bytes_end() <= s.bytes_end(); } MemoryBufferRef ScriptLexer::getCurrentMB() { // Find input buffer containing the current token. - assert(!MBs.empty() && Pos > 0); - for (MemoryBufferRef MB : MBs) - if (encloses(MB.getBuffer(), Tokens[Pos - 1])) - return MB; + assert(!mbs.empty() && pos > 0); + for (MemoryBufferRef mb : mbs) + if (encloses(mb.getBuffer(), tokens[pos - 1])) + return mb; llvm_unreachable("getCurrentMB: failed to find a token"); } Index: lld/trunk/ELF/ScriptParser.h =================================================================== --- lld/trunk/ELF/ScriptParser.h +++ lld/trunk/ELF/ScriptParser.h @@ -17,15 +17,15 @@ // Parses a linker script. Calling this function updates // Config and ScriptConfig. -void readLinkerScript(MemoryBufferRef MB); +void readLinkerScript(MemoryBufferRef mb); // Parses a version script. -void readVersionScript(MemoryBufferRef MB); +void readVersionScript(MemoryBufferRef mb); -void readDynamicList(MemoryBufferRef MB); +void readDynamicList(MemoryBufferRef mb); // Parses the defsym expression. -void readDefsym(StringRef Name, MemoryBufferRef MB); +void readDefsym(StringRef name, MemoryBufferRef mb); } // namespace elf } // namespace lld Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -43,15 +43,15 @@ namespace { class ScriptParser final : ScriptLexer { public: - ScriptParser(MemoryBufferRef MB) : ScriptLexer(MB) { + ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) { // Initialize IsUnderSysroot - if (Config->Sysroot == "") + if (config->sysroot == "") return; - StringRef Path = MB.getBufferIdentifier(); - for (; !Path.empty(); Path = sys::path::parent_path(Path)) { - if (!sys::fs::equivalent(Config->Sysroot, Path)) + StringRef path = mb.getBufferIdentifier(); + for (; !path.empty(); path = sys::path::parent_path(path)) { + if (!sys::fs::equivalent(config->sysroot, path)) continue; - IsUnderSysroot = true; + isUnderSysroot = true; return; } } @@ -59,10 +59,10 @@ void readLinkerScript(); void readVersionScript(); void readDynamicList(); - void readDefsym(StringRef Name); + void readDefsym(StringRef name); private: - void addFile(StringRef Path); + void addFile(StringRef path); void readAsNeeded(); void readEntry(); @@ -82,23 +82,23 @@ void readVersion(); void readVersionScriptCommand(); - SymbolAssignment *readSymbolAssignment(StringRef Name); - ByteCommand *readByteCommand(StringRef Tok); + SymbolAssignment *readSymbolAssignment(StringRef name); + ByteCommand *readByteCommand(StringRef tok); std::array readFill(); - bool readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2); - void readSectionAddressType(OutputSection *Cmd); + bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2); + void readSectionAddressType(OutputSection *cmd); OutputSection *readOverlaySectionDescription(); - OutputSection *readOutputSectionDescription(StringRef OutSec); + OutputSection *readOutputSectionDescription(StringRef outSec); std::vector readOverlay(); std::vector readOutputSectionPhdrs(); - InputSectionDescription *readInputSectionDescription(StringRef Tok); + InputSectionDescription *readInputSectionDescription(StringRef tok); StringMatcher readFilePatterns(); std::vector readInputSectionsList(); - InputSectionDescription *readInputSectionRules(StringRef FilePattern); + InputSectionDescription *readInputSectionRules(StringRef filePattern); unsigned readPhdrType(); SortSectionPolicy readSortKind(); - SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); - SymbolAssignment *readAssignment(StringRef Tok); + SymbolAssignment *readProvideHidden(bool provide, bool hidden); + SymbolAssignment *readAssignment(StringRef tok); void readSort(); Expr readAssert(); Expr readConstant(); @@ -107,88 +107,88 @@ uint64_t readMemoryAssignment(StringRef, StringRef, StringRef); std::pair readMemoryAttributes(); - Expr combine(StringRef Op, Expr L, Expr R); + Expr combine(StringRef op, Expr l, Expr r); Expr readExpr(); - Expr readExpr1(Expr Lhs, int MinPrec); + Expr readExpr1(Expr lhs, int minPrec); StringRef readParenLiteral(); Expr readPrimary(); - Expr readTernary(Expr Cond); + Expr readTernary(Expr cond); Expr readParenExpr(); // For parsing version script. std::vector readVersionExtern(); void readAnonymousDeclaration(); - void readVersionDeclaration(StringRef VerStr); + void readVersionDeclaration(StringRef verStr); std::pair, std::vector> readSymbols(); // True if a script being read is in a subdirectory specified by -sysroot. - bool IsUnderSysroot = false; + bool isUnderSysroot = false; // A set to detect an INCLUDE() cycle. - StringSet<> Seen; + StringSet<> seen; }; } // namespace -static StringRef unquote(StringRef S) { - if (S.startswith("\"")) - return S.substr(1, S.size() - 2); - return S; +static StringRef unquote(StringRef s) { + if (s.startswith("\"")) + return s.substr(1, s.size() - 2); + return s; } // Some operations only support one non absolute value. Move the // absolute one to the right hand side for convenience. -static void moveAbsRight(ExprValue &A, ExprValue &B) { - if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute())) - std::swap(A, B); - if (!B.isAbsolute()) - error(A.Loc + ": at least one side of the expression must be absolute"); +static void moveAbsRight(ExprValue &a, ExprValue &b) { + if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute())) + std::swap(a, b); + if (!b.isAbsolute()) + error(a.loc + ": at least one side of the expression must be absolute"); } -static ExprValue add(ExprValue A, ExprValue B) { - moveAbsRight(A, B); - return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc}; +static ExprValue add(ExprValue a, ExprValue b) { + moveAbsRight(a, b); + return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc}; } -static ExprValue sub(ExprValue A, ExprValue B) { +static ExprValue sub(ExprValue a, ExprValue b) { // The distance between two symbols in sections is absolute. - if (!A.isAbsolute() && !B.isAbsolute()) - return A.getValue() - B.getValue(); - return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc}; + if (!a.isAbsolute() && !b.isAbsolute()) + return a.getValue() - b.getValue(); + return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc}; } -static ExprValue bitAnd(ExprValue A, ExprValue B) { - moveAbsRight(A, B); - return {A.Sec, A.ForceAbsolute, - (A.getValue() & B.getValue()) - A.getSecAddr(), A.Loc}; +static ExprValue bitAnd(ExprValue a, ExprValue b) { + moveAbsRight(a, b); + return {a.sec, a.forceAbsolute, + (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc}; } -static ExprValue bitOr(ExprValue A, ExprValue B) { - moveAbsRight(A, B); - return {A.Sec, A.ForceAbsolute, - (A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc}; +static ExprValue bitOr(ExprValue a, ExprValue b) { + moveAbsRight(a, b); + return {a.sec, a.forceAbsolute, + (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc}; } void ScriptParser::readDynamicList() { - Config->HasDynamicList = true; + config->hasDynamicList = true; expect("{"); - std::vector Locals; - std::vector Globals; - std::tie(Locals, Globals) = readSymbols(); + std::vector locals; + std::vector globals; + std::tie(locals, globals) = readSymbols(); expect(";"); if (!atEOF()) { setError("EOF expected, but got " + next()); return; } - if (!Locals.empty()) { + if (!locals.empty()) { setError("\"local:\" scope not supported in --dynamic-list"); return; } - for (SymbolVersion V : Globals) - Config->DynamicList.push_back(V); + for (SymbolVersion v : globals) + config->dynamicList.push_back(v); } void ScriptParser::readVersionScript() { @@ -204,14 +204,14 @@ } while (!atEOF() && !errorCount() && peek() != "}") { - StringRef VerStr = next(); - if (VerStr == "{") { + StringRef verStr = next(); + if (verStr == "{") { setError("anonymous version definition is used in " "combination with other version definitions"); return; } expect("{"); - readVersionDeclaration(VerStr); + readVersionDeclaration(verStr); } } @@ -223,135 +223,135 @@ void ScriptParser::readLinkerScript() { while (!atEOF()) { - StringRef Tok = next(); - if (Tok == ";") + StringRef tok = next(); + if (tok == ";") continue; - if (Tok == "ENTRY") { + if (tok == "ENTRY") { readEntry(); - } else if (Tok == "EXTERN") { + } else if (tok == "EXTERN") { readExtern(); - } else if (Tok == "GROUP") { + } else if (tok == "GROUP") { readGroup(); - } else if (Tok == "INCLUDE") { + } else if (tok == "INCLUDE") { readInclude(); - } else if (Tok == "INPUT") { + } else if (tok == "INPUT") { readInput(); - } else if (Tok == "MEMORY") { + } else if (tok == "MEMORY") { readMemory(); - } else if (Tok == "OUTPUT") { + } else if (tok == "OUTPUT") { readOutput(); - } else if (Tok == "OUTPUT_ARCH") { + } else if (tok == "OUTPUT_ARCH") { readOutputArch(); - } else if (Tok == "OUTPUT_FORMAT") { + } else if (tok == "OUTPUT_FORMAT") { readOutputFormat(); - } else if (Tok == "PHDRS") { + } else if (tok == "PHDRS") { readPhdrs(); - } else if (Tok == "REGION_ALIAS") { + } else if (tok == "REGION_ALIAS") { readRegionAlias(); - } else if (Tok == "SEARCH_DIR") { + } else if (tok == "SEARCH_DIR") { readSearchDir(); - } else if (Tok == "SECTIONS") { + } else if (tok == "SECTIONS") { readSections(); - } else if (Tok == "TARGET") { + } else if (tok == "TARGET") { readTarget(); - } else if (Tok == "VERSION") { + } else if (tok == "VERSION") { readVersion(); - } else if (SymbolAssignment *Cmd = readAssignment(Tok)) { - Script->SectionCommands.push_back(Cmd); + } else if (SymbolAssignment *cmd = readAssignment(tok)) { + script->sectionCommands.push_back(cmd); } else { - setError("unknown directive: " + Tok); + setError("unknown directive: " + tok); } } } -void ScriptParser::readDefsym(StringRef Name) { +void ScriptParser::readDefsym(StringRef name) { if (errorCount()) return; - Expr E = readExpr(); + Expr e = readExpr(); if (!atEOF()) setError("EOF expected, but got " + next()); - SymbolAssignment *Cmd = make(Name, E, getCurrentLocation()); - Script->SectionCommands.push_back(Cmd); + SymbolAssignment *cmd = make(name, e, getCurrentLocation()); + script->sectionCommands.push_back(cmd); } -void ScriptParser::addFile(StringRef S) { - if (IsUnderSysroot && S.startswith("/")) { - SmallString<128> PathData; - StringRef Path = (Config->Sysroot + S).toStringRef(PathData); - if (sys::fs::exists(Path)) { - Driver->addFile(Saver.save(Path), /*WithLOption=*/false); +void ScriptParser::addFile(StringRef s) { + if (isUnderSysroot && s.startswith("/")) { + SmallString<128> pathData; + StringRef path = (config->sysroot + s).toStringRef(pathData); + if (sys::fs::exists(path)) { + driver->addFile(Saver.save(path), /*WithLOption=*/false); return; } } - if (S.startswith("/")) { - Driver->addFile(S, /*WithLOption=*/false); - } else if (S.startswith("=")) { - if (Config->Sysroot.empty()) - Driver->addFile(S.substr(1), /*WithLOption=*/false); + if (s.startswith("/")) { + driver->addFile(s, /*WithLOption=*/false); + } else if (s.startswith("=")) { + if (config->sysroot.empty()) + driver->addFile(s.substr(1), /*WithLOption=*/false); else - Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)), + driver->addFile(Saver.save(config->sysroot + "/" + s.substr(1)), /*WithLOption=*/false); - } else if (S.startswith("-l")) { - Driver->addLibrary(S.substr(2)); - } else if (sys::fs::exists(S)) { - Driver->addFile(S, /*WithLOption=*/false); + } else if (s.startswith("-l")) { + driver->addLibrary(s.substr(2)); + } else if (sys::fs::exists(s)) { + driver->addFile(s, /*WithLOption=*/false); } else { - if (Optional Path = findFromSearchPaths(S)) - Driver->addFile(Saver.save(*Path), /*WithLOption=*/true); + if (Optional path = findFromSearchPaths(s)) + driver->addFile(Saver.save(*path), /*WithLOption=*/true); else - setError("unable to find " + S); + setError("unable to find " + s); } } void ScriptParser::readAsNeeded() { expect("("); - bool Orig = Config->AsNeeded; - Config->AsNeeded = true; + bool orig = config->asNeeded; + config->asNeeded = true; while (!errorCount() && !consume(")")) addFile(unquote(next())); - Config->AsNeeded = Orig; + config->asNeeded = orig; } void ScriptParser::readEntry() { // -e takes predecence over ENTRY(). expect("("); - StringRef Tok = next(); - if (Config->Entry.empty()) - Config->Entry = Tok; + StringRef tok = next(); + if (config->entry.empty()) + config->entry = tok; expect(")"); } void ScriptParser::readExtern() { expect("("); while (!errorCount() && !consume(")")) - Config->Undefined.push_back(unquote(next())); + config->undefined.push_back(unquote(next())); } void ScriptParser::readGroup() { - bool Orig = InputFile::IsInGroup; - InputFile::IsInGroup = true; + bool orig = InputFile::isInGroup; + InputFile::isInGroup = true; readInput(); - InputFile::IsInGroup = Orig; - if (!Orig) - ++InputFile::NextGroupId; + InputFile::isInGroup = orig; + if (!orig) + ++InputFile::nextGroupId; } void ScriptParser::readInclude() { - StringRef Tok = unquote(next()); + StringRef tok = unquote(next()); - if (!Seen.insert(Tok).second) { + if (!seen.insert(tok).second) { setError("there is a cycle in linker script INCLUDEs"); return; } - if (Optional Path = searchScript(Tok)) { - if (Optional MB = readFile(*Path)) - tokenize(*MB); + if (Optional path = searchScript(tok)) { + if (Optional mb = readFile(*path)) + tokenize(*mb); return; } - setError("cannot find linker script " + Tok); + setError("cannot find linker script " + tok); } void ScriptParser::readInput() { @@ -367,9 +367,9 @@ void ScriptParser::readOutput() { // -o takes predecence over OUTPUT(). expect("("); - StringRef Tok = next(); - if (Config->OutputFile.empty()) - Config->OutputFile = unquote(Tok); + StringRef tok = next(); + if (config->outputFile.empty()) + config->outputFile = unquote(tok); expect(")"); } @@ -380,8 +380,8 @@ skip(); } -static std::pair parseBfdName(StringRef S) { - return StringSwitch>(S) +static std::pair parseBfdName(StringRef s) { + return StringSwitch>(s) .Case("elf32-i386", {ELF32LEKind, EM_386}) .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) @@ -408,16 +408,16 @@ void ScriptParser::readOutputFormat() { expect("("); - StringRef Name = unquote(next()); - StringRef S = Name; - if (S.consume_back("-freebsd")) - Config->OSABI = ELFOSABI_FREEBSD; - - std::tie(Config->EKind, Config->EMachine) = parseBfdName(S); - if (Config->EMachine == EM_NONE) - setError("unknown output format name: " + Name); - if (S == "elf32-ntradlittlemips" || S == "elf32-ntradbigmips") - Config->MipsN32Abi = true; + StringRef name = unquote(next()); + StringRef s = name; + if (s.consume_back("-freebsd")) + config->osabi = ELFOSABI_FREEBSD; + + std::tie(config->ekind, config->emachine) = parseBfdName(s); + if (config->emachine == EM_NONE) + setError("unknown output format name: " + name); + if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips") + config->mipsN32Abi = true; if (consume(")")) return; @@ -432,46 +432,46 @@ expect("{"); while (!errorCount() && !consume("}")) { - PhdrsCommand Cmd; - Cmd.Name = next(); - Cmd.Type = readPhdrType(); + PhdrsCommand cmd; + cmd.name = next(); + cmd.type = readPhdrType(); while (!errorCount() && !consume(";")) { if (consume("FILEHDR")) - Cmd.HasFilehdr = true; + cmd.hasFilehdr = true; else if (consume("PHDRS")) - Cmd.HasPhdrs = true; + cmd.hasPhdrs = true; else if (consume("AT")) - Cmd.LMAExpr = readParenExpr(); + cmd.lmaExpr = readParenExpr(); else if (consume("FLAGS")) - Cmd.Flags = readParenExpr()().getValue(); + cmd.flags = readParenExpr()().getValue(); else setError("unexpected header attribute: " + next()); } - Script->PhdrsCommands.push_back(Cmd); + script->phdrsCommands.push_back(cmd); } } void ScriptParser::readRegionAlias() { expect("("); - StringRef Alias = unquote(next()); + StringRef alias = unquote(next()); expect(","); - StringRef Name = next(); + StringRef name = next(); expect(")"); - if (Script->MemoryRegions.count(Alias)) - setError("redefinition of memory region '" + Alias + "'"); - if (!Script->MemoryRegions.count(Name)) - setError("memory region '" + Name + "' is not defined"); - Script->MemoryRegions.insert({Alias, Script->MemoryRegions[Name]}); + if (script->memoryRegions.count(alias)) + setError("redefinition of memory region '" + alias + "'"); + if (!script->memoryRegions.count(name)) + setError("memory region '" + name + "' is not defined"); + script->memoryRegions.insert({alias, script->memoryRegions[name]}); } void ScriptParser::readSearchDir() { expect("("); - StringRef Tok = next(); - if (!Config->Nostdlib) - Config->SearchPaths.push_back(unquote(Tok)); + StringRef tok = next(); + if (!config->nostdlib) + config->searchPaths.push_back(unquote(tok)); expect(")"); } @@ -483,83 +483,83 @@ // VA and LMA expressions are optional, though for simplicity of // implementation we assume they are not. That is what OVERLAY was designed // for first of all: to allow sections with overlapping VAs at different LMAs. - Expr AddrExpr = readExpr(); + Expr addrExpr = readExpr(); expect(":"); expect("AT"); - Expr LMAExpr = readParenExpr(); + Expr lmaExpr = readParenExpr(); expect("{"); - std::vector V; - OutputSection *Prev = nullptr; + std::vector v; + OutputSection *prev = nullptr; while (!errorCount() && !consume("}")) { // VA is the same for all sections. The LMAs are consecutive in memory // starting from the base load address specified. - OutputSection *OS = readOverlaySectionDescription(); - OS->AddrExpr = AddrExpr; - if (Prev) - OS->LMAExpr = [=] { return Prev->getLMA() + Prev->Size; }; + OutputSection *os = readOverlaySectionDescription(); + os->addrExpr = addrExpr; + if (prev) + os->lmaExpr = [=] { return prev->getLMA() + prev->size; }; else - OS->LMAExpr = LMAExpr; - V.push_back(OS); - Prev = OS; + os->lmaExpr = lmaExpr; + v.push_back(os); + prev = os; } // According to the specification, at the end of the overlay, the location // counter should be equal to the overlay base address plus size of the // largest section seen in the overlay. // Here we want to create the Dot assignment command to achieve that. - Expr MoveDot = [=] { - uint64_t Max = 0; - for (BaseCommand *Cmd : V) - Max = std::max(Max, cast(Cmd)->Size); - return AddrExpr().getValue() + Max; + Expr moveDot = [=] { + uint64_t max = 0; + for (BaseCommand *cmd : v) + max = std::max(max, cast(cmd)->size); + return addrExpr().getValue() + max; }; - V.push_back(make(".", MoveDot, getCurrentLocation())); - return V; + v.push_back(make(".", moveDot, getCurrentLocation())); + return v; } void ScriptParser::readSections() { - Script->HasSectionsCommand = true; + script->hasSectionsCommand = true; // -no-rosegment is used to avoid placing read only non-executable sections in // their own segment. We do the same if SECTIONS command is present in linker // script. See comment for computeFlags(). - Config->SingleRoRx = true; + config->singleRoRx = true; expect("{"); - std::vector V; + std::vector v; while (!errorCount() && !consume("}")) { - StringRef Tok = next(); - if (Tok == "OVERLAY") { - for (BaseCommand *Cmd : readOverlay()) - V.push_back(Cmd); + StringRef tok = next(); + if (tok == "OVERLAY") { + for (BaseCommand *cmd : readOverlay()) + v.push_back(cmd); continue; - } else if (Tok == "INCLUDE") { + } else if (tok == "INCLUDE") { readInclude(); continue; } - if (BaseCommand *Cmd = readAssignment(Tok)) - V.push_back(Cmd); + if (BaseCommand *cmd = readAssignment(tok)) + v.push_back(cmd); else - V.push_back(readOutputSectionDescription(Tok)); + v.push_back(readOutputSectionDescription(tok)); } if (!atEOF() && consume("INSERT")) { - std::vector *Dest = nullptr; + std::vector *dest = nullptr; if (consume("AFTER")) - Dest = &Script->InsertAfterCommands[next()]; + dest = &script->insertAfterCommands[next()]; else if (consume("BEFORE")) - Dest = &Script->InsertBeforeCommands[next()]; + dest = &script->insertBeforeCommands[next()]; else setError("expected AFTER/BEFORE, but got '" + next() + "'"); - if (Dest) - Dest->insert(Dest->end(), V.begin(), V.end()); + if (dest) + dest->insert(dest->end(), v.begin(), v.end()); return; } - Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(), - V.end()); + script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), + v.end()); } void ScriptParser::readTarget() { @@ -568,19 +568,19 @@ // for --format. We recognize only /^elf/ and "binary" in the linker // script as well. expect("("); - StringRef Tok = next(); + StringRef tok = next(); expect(")"); - if (Tok.startswith("elf")) - Config->FormatBinary = false; - else if (Tok == "binary") - Config->FormatBinary = true; + if (tok.startswith("elf")) + config->formatBinary = false; + else if (tok == "binary") + config->formatBinary = true; else - setError("unknown target: " + Tok); + setError("unknown target: " + tok); } -static int precedence(StringRef Op) { - return StringSwitch(Op) +static int precedence(StringRef op) { + return StringSwitch(op) .Cases("*", "/", "%", 8) .Cases("+", "-", 7) .Cases("<<", ">>", 6) @@ -593,10 +593,10 @@ } StringMatcher ScriptParser::readFilePatterns() { - std::vector V; + std::vector v; while (!errorCount() && !consume(")")) - V.push_back(next()); - return StringMatcher(V); + v.push_back(next()); + return StringMatcher(v); } SortSectionPolicy ScriptParser::readSortKind() { @@ -625,24 +625,24 @@ // The semantics of that is section .foo in any file, section .bar in // any file but a.o, and section .baz in any file but b.o. std::vector ScriptParser::readInputSectionsList() { - std::vector Ret; + std::vector ret; while (!errorCount() && peek() != ")") { - StringMatcher ExcludeFilePat; + StringMatcher excludeFilePat; if (consume("EXCLUDE_FILE")) { expect("("); - ExcludeFilePat = readFilePatterns(); + excludeFilePat = readFilePatterns(); } - std::vector V; + std::vector v; while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE") - V.push_back(unquote(next())); + v.push_back(unquote(next())); - if (!V.empty()) - Ret.push_back({std::move(ExcludeFilePat), StringMatcher(V)}); + if (!v.empty()) + ret.push_back({std::move(excludeFilePat), StringMatcher(v)}); else setError("section pattern is expected"); } - return Ret; + return ret; } // Reads contents of "SECTIONS" directive. That directive contains a @@ -657,52 +657,52 @@ // // is parsed by readInputSectionsList(). InputSectionDescription * -ScriptParser::readInputSectionRules(StringRef FilePattern) { - auto *Cmd = make(FilePattern); +ScriptParser::readInputSectionRules(StringRef filePattern) { + auto *cmd = make(filePattern); expect("("); while (!errorCount() && !consume(")")) { - SortSectionPolicy Outer = readSortKind(); - SortSectionPolicy Inner = SortSectionPolicy::Default; - std::vector V; - if (Outer != SortSectionPolicy::Default) { + SortSectionPolicy outer = readSortKind(); + SortSectionPolicy inner = SortSectionPolicy::Default; + std::vector v; + if (outer != SortSectionPolicy::Default) { expect("("); - Inner = readSortKind(); - if (Inner != SortSectionPolicy::Default) { + inner = readSortKind(); + if (inner != SortSectionPolicy::Default) { expect("("); - V = readInputSectionsList(); + v = readInputSectionsList(); expect(")"); } else { - V = readInputSectionsList(); + v = readInputSectionsList(); } expect(")"); } else { - V = readInputSectionsList(); + v = readInputSectionsList(); } - for (SectionPattern &Pat : V) { - Pat.SortInner = Inner; - Pat.SortOuter = Outer; + for (SectionPattern &pat : v) { + pat.sortInner = inner; + pat.sortOuter = outer; } - std::move(V.begin(), V.end(), std::back_inserter(Cmd->SectionPatterns)); + std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns)); } - return Cmd; + return cmd; } InputSectionDescription * -ScriptParser::readInputSectionDescription(StringRef Tok) { +ScriptParser::readInputSectionDescription(StringRef tok) { // Input section wildcard can be surrounded by KEEP. // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep - if (Tok == "KEEP") { + if (tok == "KEEP") { expect("("); - StringRef FilePattern = next(); - InputSectionDescription *Cmd = readInputSectionRules(FilePattern); + StringRef filePattern = next(); + InputSectionDescription *cmd = readInputSectionRules(filePattern); expect(")"); - Script->KeptSections.push_back(Cmd); - return Cmd; + script->keptSections.push_back(cmd); + return cmd; } - return readInputSectionRules(Tok); + return readInputSectionRules(tok); } void ScriptParser::readSort() { @@ -713,33 +713,33 @@ Expr ScriptParser::readAssert() { expect("("); - Expr E = readExpr(); + Expr e = readExpr(); expect(","); - StringRef Msg = unquote(next()); + StringRef msg = unquote(next()); expect(")"); return [=] { - if (!E().getValue()) - error(Msg); - return Script->getDot(); + if (!e().getValue()) + error(msg); + return script->getDot(); }; } // Tries to read the special directive for an output section definition which // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)". // Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below. -bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2) { - if (Tok1 != "(") +bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) { + if (tok1 != "(") return false; - if (Tok2 != "NOLOAD" && Tok2 != "COPY" && Tok2 != "INFO" && Tok2 != "OVERLAY") + if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" && tok2 != "OVERLAY") return false; expect("("); if (consume("NOLOAD")) { - Cmd->Noload = true; + cmd->noload = true; } else { skip(); // This is "COPY", "INFO" or "OVERLAY". - Cmd->NonAlloc = true; + cmd->nonAlloc = true; } expect(")"); return true; @@ -756,121 +756,121 @@ // // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html -void ScriptParser::readSectionAddressType(OutputSection *Cmd) { - if (readSectionDirective(Cmd, peek(), peek2())) +void ScriptParser::readSectionAddressType(OutputSection *cmd) { + if (readSectionDirective(cmd, peek(), peek2())) return; - Cmd->AddrExpr = readExpr(); - if (peek() == "(" && !readSectionDirective(Cmd, "(", peek2())) + cmd->addrExpr = readExpr(); + if (peek() == "(" && !readSectionDirective(cmd, "(", peek2())) setError("unknown section directive: " + peek2()); } -static Expr checkAlignment(Expr E, std::string &Loc) { +static Expr checkAlignment(Expr e, std::string &loc) { return [=] { - uint64_t Alignment = std::max((uint64_t)1, E().getValue()); - if (!isPowerOf2_64(Alignment)) { - error(Loc + ": alignment must be power of 2"); + uint64_t alignment = std::max((uint64_t)1, e().getValue()); + if (!isPowerOf2_64(alignment)) { + error(loc + ": alignment must be power of 2"); return (uint64_t)1; // Return a dummy value. } - return Alignment; + return alignment; }; } OutputSection *ScriptParser::readOverlaySectionDescription() { - OutputSection *Cmd = - Script->createOutputSection(next(), getCurrentLocation()); - Cmd->InOverlay = true; + OutputSection *cmd = + script->createOutputSection(next(), getCurrentLocation()); + cmd->inOverlay = true; expect("{"); while (!errorCount() && !consume("}")) - Cmd->SectionCommands.push_back(readInputSectionRules(next())); - Cmd->Phdrs = readOutputSectionPhdrs(); - return Cmd; + cmd->sectionCommands.push_back(readInputSectionRules(next())); + cmd->phdrs = readOutputSectionPhdrs(); + return cmd; } -OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { - OutputSection *Cmd = - Script->createOutputSection(OutSec, getCurrentLocation()); +OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { + OutputSection *cmd = + script->createOutputSection(outSec, getCurrentLocation()); - size_t SymbolsReferenced = Script->ReferencedSymbols.size(); + size_t symbolsReferenced = script->referencedSymbols.size(); if (peek() != ":") - readSectionAddressType(Cmd); + readSectionAddressType(cmd); expect(":"); - std::string Location = getCurrentLocation(); + std::string location = getCurrentLocation(); if (consume("AT")) - Cmd->LMAExpr = readParenExpr(); + cmd->lmaExpr = readParenExpr(); if (consume("ALIGN")) - Cmd->AlignExpr = checkAlignment(readParenExpr(), Location); + cmd->alignExpr = checkAlignment(readParenExpr(), location); if (consume("SUBALIGN")) - Cmd->SubalignExpr = checkAlignment(readParenExpr(), Location); + cmd->subalignExpr = checkAlignment(readParenExpr(), location); // Parse constraints. if (consume("ONLY_IF_RO")) - Cmd->Constraint = ConstraintKind::ReadOnly; + cmd->constraint = ConstraintKind::ReadOnly; if (consume("ONLY_IF_RW")) - Cmd->Constraint = ConstraintKind::ReadWrite; + cmd->constraint = ConstraintKind::ReadWrite; expect("{"); while (!errorCount() && !consume("}")) { - StringRef Tok = next(); - if (Tok == ";") { + StringRef tok = next(); + if (tok == ";") { // Empty commands are allowed. Do nothing here. - } else if (SymbolAssignment *Assign = readAssignment(Tok)) { - Cmd->SectionCommands.push_back(Assign); - } else if (ByteCommand *Data = readByteCommand(Tok)) { - Cmd->SectionCommands.push_back(Data); - } else if (Tok == "CONSTRUCTORS") { + } else if (SymbolAssignment *assign = readAssignment(tok)) { + cmd->sectionCommands.push_back(assign); + } else if (ByteCommand *data = readByteCommand(tok)) { + cmd->sectionCommands.push_back(data); + } else if (tok == "CONSTRUCTORS") { // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors // by name. This is for very old file formats such as ECOFF/XCOFF. // For ELF, we should ignore. - } else if (Tok == "FILL") { + } else if (tok == "FILL") { // We handle the FILL command as an alias for =fillexp section attribute, // which is different from what GNU linkers do. // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html - Cmd->Filler = readFill(); - } else if (Tok == "SORT") { + cmd->filler = readFill(); + } else if (tok == "SORT") { readSort(); - } else if (Tok == "INCLUDE") { + } else if (tok == "INCLUDE") { readInclude(); } else if (peek() == "(") { - Cmd->SectionCommands.push_back(readInputSectionDescription(Tok)); + cmd->sectionCommands.push_back(readInputSectionDescription(tok)); } else { // We have a file name and no input sections description. It is not a // commonly used syntax, but still acceptable. In that case, all sections // from the file will be included. - auto *ISD = make(Tok); - ISD->SectionPatterns.push_back({{}, StringMatcher({"*"})}); - Cmd->SectionCommands.push_back(ISD); + auto *isd = make(tok); + isd->sectionPatterns.push_back({{}, StringMatcher({"*"})}); + cmd->sectionCommands.push_back(isd); } } if (consume(">")) - Cmd->MemoryRegionName = next(); + cmd->memoryRegionName = next(); if (consume("AT")) { expect(">"); - Cmd->LMARegionName = next(); + cmd->lmaRegionName = next(); } - if (Cmd->LMAExpr && !Cmd->LMARegionName.empty()) + if (cmd->lmaExpr && !cmd->lmaRegionName.empty()) error("section can't have both LMA and a load region"); - Cmd->Phdrs = readOutputSectionPhdrs(); + cmd->phdrs = readOutputSectionPhdrs(); if (peek() == "=" || peek().startswith("=")) { - InExpr = true; + inExpr = true; consume("="); - Cmd->Filler = readFill(); - InExpr = false; + cmd->filler = readFill(); + inExpr = false; } // Consume optional comma following output section command. consume(","); - if (Script->ReferencedSymbols.size() > SymbolsReferenced) - Cmd->ExpressionsUseSymbols = true; - return Cmd; + if (script->referencedSymbols.size() > symbolsReferenced) + cmd->expressionsUseSymbols = true; + return cmd; } // Reads a `=` expression and returns its value as a big-endian number. @@ -881,59 +881,59 @@ // size, while ld.gold always handles it as a 32-bit big-endian number. // We are compatible with ld.gold because it's easier to implement. std::array ScriptParser::readFill() { - uint64_t Value = readExpr()().Val; - if (Value > UINT32_MAX) + uint64_t value = readExpr()().val; + if (value > UINT32_MAX) setError("filler expression result does not fit 32-bit: 0x" + - Twine::utohexstr(Value)); + Twine::utohexstr(value)); - std::array Buf; - write32be(Buf.data(), (uint32_t)Value); - return Buf; + std::array buf; + write32be(buf.data(), (uint32_t)value); + return buf; } -SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { +SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) { expect("("); - SymbolAssignment *Cmd = readSymbolAssignment(next()); - Cmd->Provide = Provide; - Cmd->Hidden = Hidden; + SymbolAssignment *cmd = readSymbolAssignment(next()); + cmd->provide = provide; + cmd->hidden = hidden; expect(")"); - return Cmd; + return cmd; } -SymbolAssignment *ScriptParser::readAssignment(StringRef Tok) { +SymbolAssignment *ScriptParser::readAssignment(StringRef tok) { // Assert expression returns Dot, so this is equal to ".=." - if (Tok == "ASSERT") + if (tok == "ASSERT") return make(".", readAssert(), getCurrentLocation()); - size_t OldPos = Pos; - SymbolAssignment *Cmd = nullptr; + size_t oldPos = pos; + SymbolAssignment *cmd = nullptr; if (peek() == "=" || peek() == "+=") - Cmd = readSymbolAssignment(Tok); - else if (Tok == "PROVIDE") - Cmd = readProvideHidden(true, false); - else if (Tok == "HIDDEN") - Cmd = readProvideHidden(false, true); - else if (Tok == "PROVIDE_HIDDEN") - Cmd = readProvideHidden(true, true); - - if (Cmd) { - Cmd->CommandString = - Tok.str() + " " + - llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); + cmd = readSymbolAssignment(tok); + else if (tok == "PROVIDE") + cmd = readProvideHidden(true, false); + else if (tok == "HIDDEN") + cmd = readProvideHidden(false, true); + else if (tok == "PROVIDE_HIDDEN") + cmd = readProvideHidden(true, true); + + if (cmd) { + cmd->commandString = + tok.str() + " " + + llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " "); expect(";"); } - return Cmd; + return cmd; } -SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) { - StringRef Op = next(); - assert(Op == "=" || Op == "+="); - Expr E = readExpr(); - if (Op == "+=") { - std::string Loc = getCurrentLocation(); - E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); }; +SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) { + StringRef op = next(); + assert(op == "=" || op == "+="); + Expr e = readExpr(); + if (op == "+=") { + std::string loc = getCurrentLocation(); + e = [=] { return add(script->getSymbolValue(name, loc), e()); }; } - return make(Name, E, getCurrentLocation()); + return make(name, e, getCurrentLocation()); } // This is an operator-precedence parser to parse a linker @@ -941,178 +941,178 @@ Expr ScriptParser::readExpr() { // Our lexer is context-aware. Set the in-expression bit so that // they apply different tokenization rules. - bool Orig = InExpr; - InExpr = true; - Expr E = readExpr1(readPrimary(), 0); - InExpr = Orig; - return E; -} - -Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) { - if (Op == "+") - return [=] { return add(L(), R()); }; - if (Op == "-") - return [=] { return sub(L(), R()); }; - if (Op == "*") - return [=] { return L().getValue() * R().getValue(); }; - if (Op == "/") { - std::string Loc = getCurrentLocation(); + bool orig = inExpr; + inExpr = true; + Expr e = readExpr1(readPrimary(), 0); + inExpr = orig; + return e; +} + +Expr ScriptParser::combine(StringRef op, Expr l, Expr r) { + if (op == "+") + return [=] { return add(l(), r()); }; + if (op == "-") + return [=] { return sub(l(), r()); }; + if (op == "*") + return [=] { return l().getValue() * r().getValue(); }; + if (op == "/") { + std::string loc = getCurrentLocation(); return [=]() -> uint64_t { - if (uint64_t RV = R().getValue()) - return L().getValue() / RV; - error(Loc + ": division by zero"); + if (uint64_t rv = r().getValue()) + return l().getValue() / rv; + error(loc + ": division by zero"); return 0; }; } - if (Op == "%") { - std::string Loc = getCurrentLocation(); + if (op == "%") { + std::string loc = getCurrentLocation(); return [=]() -> uint64_t { - if (uint64_t RV = R().getValue()) - return L().getValue() % RV; - error(Loc + ": modulo by zero"); + if (uint64_t rv = r().getValue()) + return l().getValue() % rv; + error(loc + ": modulo by zero"); return 0; }; } - if (Op == "<<") - return [=] { return L().getValue() << R().getValue(); }; - if (Op == ">>") - return [=] { return L().getValue() >> R().getValue(); }; - if (Op == "<") - return [=] { return L().getValue() < R().getValue(); }; - if (Op == ">") - return [=] { return L().getValue() > R().getValue(); }; - if (Op == ">=") - return [=] { return L().getValue() >= R().getValue(); }; - if (Op == "<=") - return [=] { return L().getValue() <= R().getValue(); }; - if (Op == "==") - return [=] { return L().getValue() == R().getValue(); }; - if (Op == "!=") - return [=] { return L().getValue() != R().getValue(); }; - if (Op == "||") - return [=] { return L().getValue() || R().getValue(); }; - if (Op == "&&") - return [=] { return L().getValue() && R().getValue(); }; - if (Op == "&") - return [=] { return bitAnd(L(), R()); }; - if (Op == "|") - return [=] { return bitOr(L(), R()); }; + if (op == "<<") + return [=] { return l().getValue() << r().getValue(); }; + if (op == ">>") + return [=] { return l().getValue() >> r().getValue(); }; + if (op == "<") + return [=] { return l().getValue() < r().getValue(); }; + if (op == ">") + return [=] { return l().getValue() > r().getValue(); }; + if (op == ">=") + return [=] { return l().getValue() >= r().getValue(); }; + if (op == "<=") + return [=] { return l().getValue() <= r().getValue(); }; + if (op == "==") + return [=] { return l().getValue() == r().getValue(); }; + if (op == "!=") + return [=] { return l().getValue() != r().getValue(); }; + if (op == "||") + return [=] { return l().getValue() || r().getValue(); }; + if (op == "&&") + return [=] { return l().getValue() && r().getValue(); }; + if (op == "&") + return [=] { return bitAnd(l(), r()); }; + if (op == "|") + return [=] { return bitOr(l(), r()); }; llvm_unreachable("invalid operator"); } // This is a part of the operator-precedence parser. This function // assumes that the remaining token stream starts with an operator. -Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { +Expr ScriptParser::readExpr1(Expr lhs, int minPrec) { while (!atEOF() && !errorCount()) { // Read an operator and an expression. if (consume("?")) - return readTernary(Lhs); - StringRef Op1 = peek(); - if (precedence(Op1) < MinPrec) + return readTernary(lhs); + StringRef op1 = peek(); + if (precedence(op1) < minPrec) break; skip(); - Expr Rhs = readPrimary(); + Expr rhs = readPrimary(); // Evaluate the remaining part of the expression first if the // next operator has greater precedence than the previous one. // For example, if we have read "+" and "3", and if the next // operator is "*", then we'll evaluate 3 * ... part first. while (!atEOF()) { - StringRef Op2 = peek(); - if (precedence(Op2) <= precedence(Op1)) + StringRef op2 = peek(); + if (precedence(op2) <= precedence(op1)) break; - Rhs = readExpr1(Rhs, precedence(Op2)); + rhs = readExpr1(rhs, precedence(op2)); } - Lhs = combine(Op1, Lhs, Rhs); + lhs = combine(op1, lhs, rhs); } - return Lhs; + return lhs; } Expr ScriptParser::getPageSize() { - std::string Location = getCurrentLocation(); + std::string location = getCurrentLocation(); return [=]() -> uint64_t { - if (Target) - return Config->CommonPageSize; - error(Location + ": unable to calculate page size"); + if (target) + return config->commonPageSize; + error(location + ": unable to calculate page size"); return 4096; // Return a dummy value. }; } Expr ScriptParser::readConstant() { - StringRef S = readParenLiteral(); - if (S == "COMMONPAGESIZE") + StringRef s = readParenLiteral(); + if (s == "COMMONPAGESIZE") return getPageSize(); - if (S == "MAXPAGESIZE") - return [] { return Config->MaxPageSize; }; - setError("unknown constant: " + S); + if (s == "MAXPAGESIZE") + return [] { return config->maxPageSize; }; + setError("unknown constant: " + s); return [] { return 0; }; } // Parses Tok as an integer. It recognizes hexadecimal (prefixed with // "0x" or suffixed with "H") and decimal numbers. Decimal numbers may // have "K" (Ki) or "M" (Mi) suffixes. -static Optional parseInt(StringRef Tok) { +static Optional parseInt(StringRef tok) { // Hexadecimal - uint64_t Val; - if (Tok.startswith_lower("0x")) { - if (!to_integer(Tok.substr(2), Val, 16)) + uint64_t val; + if (tok.startswith_lower("0x")) { + if (!to_integer(tok.substr(2), val, 16)) return None; - return Val; + return val; } - if (Tok.endswith_lower("H")) { - if (!to_integer(Tok.drop_back(), Val, 16)) + if (tok.endswith_lower("H")) { + if (!to_integer(tok.drop_back(), val, 16)) return None; - return Val; + return val; } // Decimal - if (Tok.endswith_lower("K")) { - if (!to_integer(Tok.drop_back(), Val, 10)) + if (tok.endswith_lower("K")) { + if (!to_integer(tok.drop_back(), val, 10)) return None; - return Val * 1024; + return val * 1024; } - if (Tok.endswith_lower("M")) { - if (!to_integer(Tok.drop_back(), Val, 10)) + if (tok.endswith_lower("M")) { + if (!to_integer(tok.drop_back(), val, 10)) return None; - return Val * 1024 * 1024; + return val * 1024 * 1024; } - if (!to_integer(Tok, Val, 10)) + if (!to_integer(tok, val, 10)) return None; - return Val; + return val; } -ByteCommand *ScriptParser::readByteCommand(StringRef Tok) { - int Size = StringSwitch(Tok) +ByteCommand *ScriptParser::readByteCommand(StringRef tok) { + int size = StringSwitch(tok) .Case("BYTE", 1) .Case("SHORT", 2) .Case("LONG", 4) .Case("QUAD", 8) .Default(-1); - if (Size == -1) + if (size == -1) return nullptr; - size_t OldPos = Pos; - Expr E = readParenExpr(); - std::string CommandString = - Tok.str() + " " + - llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); - return make(E, Size, CommandString); + size_t oldPos = pos; + Expr e = readParenExpr(); + std::string commandString = + tok.str() + " " + + llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " "); + return make(e, size, commandString); } StringRef ScriptParser::readParenLiteral() { expect("("); - bool Orig = InExpr; - InExpr = false; - StringRef Tok = next(); - InExpr = Orig; + bool orig = inExpr; + inExpr = false; + StringRef tok = next(); + inExpr = orig; expect(")"); - return Tok; + return tok; } -static void checkIfExists(OutputSection *Cmd, StringRef Location) { - if (Cmd->Location.empty() && Script->ErrorOnMissingSection) - error(Location + ": undefined section " + Cmd->Name); +static void checkIfExists(OutputSection *cmd, StringRef location) { + if (cmd->location.empty() && script->errorOnMissingSection) + error(location + ": undefined section " + cmd->name); } Expr ScriptParser::readPrimary() { @@ -1120,85 +1120,85 @@ return readParenExpr(); if (consume("~")) { - Expr E = readPrimary(); - return [=] { return ~E().getValue(); }; + Expr e = readPrimary(); + return [=] { return ~e().getValue(); }; } if (consume("!")) { - Expr E = readPrimary(); - return [=] { return !E().getValue(); }; + Expr e = readPrimary(); + return [=] { return !e().getValue(); }; } if (consume("-")) { - Expr E = readPrimary(); - return [=] { return -E().getValue(); }; + Expr e = readPrimary(); + return [=] { return -e().getValue(); }; } - StringRef Tok = next(); - std::string Location = getCurrentLocation(); + StringRef tok = next(); + std::string location = getCurrentLocation(); // Built-in functions are parsed here. // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. - if (Tok == "ABSOLUTE") { - Expr Inner = readParenExpr(); + if (tok == "ABSOLUTE") { + Expr inner = readParenExpr(); return [=] { - ExprValue I = Inner(); - I.ForceAbsolute = true; - return I; + ExprValue i = inner(); + i.forceAbsolute = true; + return i; }; } - if (Tok == "ADDR") { - StringRef Name = readParenLiteral(); - OutputSection *Sec = Script->getOrCreateOutputSection(Name); - Sec->UsedInExpression = true; + if (tok == "ADDR") { + StringRef name = readParenLiteral(); + OutputSection *sec = script->getOrCreateOutputSection(name); + sec->usedInExpression = true; return [=]() -> ExprValue { - checkIfExists(Sec, Location); - return {Sec, false, 0, Location}; + checkIfExists(sec, location); + return {sec, false, 0, location}; }; } - if (Tok == "ALIGN") { + if (tok == "ALIGN") { expect("("); - Expr E = readExpr(); + Expr e = readExpr(); if (consume(")")) { - E = checkAlignment(E, Location); - return [=] { return alignTo(Script->getDot(), E().getValue()); }; + e = checkAlignment(e, location); + return [=] { return alignTo(script->getDot(), e().getValue()); }; } expect(","); - Expr E2 = checkAlignment(readExpr(), Location); + Expr e2 = checkAlignment(readExpr(), location); expect(")"); return [=] { - ExprValue V = E(); - V.Alignment = E2().getValue(); - return V; + ExprValue v = e(); + v.alignment = e2().getValue(); + return v; }; } - if (Tok == "ALIGNOF") { - StringRef Name = readParenLiteral(); - OutputSection *Cmd = Script->getOrCreateOutputSection(Name); + if (tok == "ALIGNOF") { + StringRef name = readParenLiteral(); + OutputSection *cmd = script->getOrCreateOutputSection(name); return [=] { - checkIfExists(Cmd, Location); - return Cmd->Alignment; + checkIfExists(cmd, location); + return cmd->alignment; }; } - if (Tok == "ASSERT") + if (tok == "ASSERT") return readAssert(); - if (Tok == "CONSTANT") + if (tok == "CONSTANT") return readConstant(); - if (Tok == "DATA_SEGMENT_ALIGN") { + if (tok == "DATA_SEGMENT_ALIGN") { expect("("); - Expr E = readExpr(); + Expr e = readExpr(); expect(","); readExpr(); expect(")"); return [=] { - return alignTo(Script->getDot(), std::max((uint64_t)1, E().getValue())); + return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue())); }; } - if (Tok == "DATA_SEGMENT_END") { + if (tok == "DATA_SEGMENT_END") { expect("("); expect("."); expect(")"); - return [] { return Script->getDot(); }; + return [] { return script->getDot(); }; } - if (Tok == "DATA_SEGMENT_RELRO_END") { + if (tok == "DATA_SEGMENT_RELRO_END") { // GNU linkers implements more complicated logic to handle // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and // just align to the next page boundary for simplicity. @@ -1207,113 +1207,113 @@ expect(","); readExpr(); expect(")"); - Expr E = getPageSize(); - return [=] { return alignTo(Script->getDot(), E().getValue()); }; + Expr e = getPageSize(); + return [=] { return alignTo(script->getDot(), e().getValue()); }; } - if (Tok == "DEFINED") { - StringRef Name = readParenLiteral(); - return [=] { return Symtab->find(Name) ? 1 : 0; }; - } - if (Tok == "LENGTH") { - StringRef Name = readParenLiteral(); - if (Script->MemoryRegions.count(Name) == 0) { - setError("memory region not defined: " + Name); + if (tok == "DEFINED") { + StringRef name = readParenLiteral(); + return [=] { return symtab->find(name) ? 1 : 0; }; + } + if (tok == "LENGTH") { + StringRef name = readParenLiteral(); + if (script->memoryRegions.count(name) == 0) { + setError("memory region not defined: " + name); return [] { return 0; }; } - return [=] { return Script->MemoryRegions[Name]->Length; }; + return [=] { return script->memoryRegions[name]->length; }; } - if (Tok == "LOADADDR") { - StringRef Name = readParenLiteral(); - OutputSection *Cmd = Script->getOrCreateOutputSection(Name); - Cmd->UsedInExpression = true; + if (tok == "LOADADDR") { + StringRef name = readParenLiteral(); + OutputSection *cmd = script->getOrCreateOutputSection(name); + cmd->usedInExpression = true; return [=] { - checkIfExists(Cmd, Location); - return Cmd->getLMA(); + checkIfExists(cmd, location); + return cmd->getLMA(); }; } - if (Tok == "MAX" || Tok == "MIN") { + if (tok == "MAX" || tok == "MIN") { expect("("); - Expr A = readExpr(); + Expr a = readExpr(); expect(","); - Expr B = readExpr(); + Expr b = readExpr(); expect(")"); - if (Tok == "MIN") - return [=] { return std::min(A().getValue(), B().getValue()); }; - return [=] { return std::max(A().getValue(), B().getValue()); }; - } - if (Tok == "ORIGIN") { - StringRef Name = readParenLiteral(); - if (Script->MemoryRegions.count(Name) == 0) { - setError("memory region not defined: " + Name); + if (tok == "MIN") + return [=] { return std::min(a().getValue(), b().getValue()); }; + return [=] { return std::max(a().getValue(), b().getValue()); }; + } + if (tok == "ORIGIN") { + StringRef name = readParenLiteral(); + if (script->memoryRegions.count(name) == 0) { + setError("memory region not defined: " + name); return [] { return 0; }; } - return [=] { return Script->MemoryRegions[Name]->Origin; }; + return [=] { return script->memoryRegions[name]->origin; }; } - if (Tok == "SEGMENT_START") { + if (tok == "SEGMENT_START") { expect("("); skip(); expect(","); - Expr E = readExpr(); + Expr e = readExpr(); expect(")"); - return [=] { return E(); }; + return [=] { return e(); }; } - if (Tok == "SIZEOF") { - StringRef Name = readParenLiteral(); - OutputSection *Cmd = Script->getOrCreateOutputSection(Name); + if (tok == "SIZEOF") { + StringRef name = readParenLiteral(); + OutputSection *cmd = script->getOrCreateOutputSection(name); // Linker script does not create an output section if its content is empty. // We want to allow SIZEOF(.foo) where .foo is a section which happened to // be empty. - return [=] { return Cmd->Size; }; + return [=] { return cmd->size; }; } - if (Tok == "SIZEOF_HEADERS") + if (tok == "SIZEOF_HEADERS") return [=] { return elf::getHeaderSize(); }; // Tok is the dot. - if (Tok == ".") - return [=] { return Script->getSymbolValue(Tok, Location); }; + if (tok == ".") + return [=] { return script->getSymbolValue(tok, location); }; // Tok is a literal number. - if (Optional Val = parseInt(Tok)) - return [=] { return *Val; }; + if (Optional val = parseInt(tok)) + return [=] { return *val; }; // Tok is a symbol name. - if (!isValidCIdentifier(Tok)) - setError("malformed number: " + Tok); - Script->ReferencedSymbols.push_back(Tok); - return [=] { return Script->getSymbolValue(Tok, Location); }; + if (!isValidCIdentifier(tok)) + setError("malformed number: " + tok); + script->referencedSymbols.push_back(tok); + return [=] { return script->getSymbolValue(tok, location); }; } -Expr ScriptParser::readTernary(Expr Cond) { - Expr L = readExpr(); +Expr ScriptParser::readTernary(Expr cond) { + Expr l = readExpr(); expect(":"); - Expr R = readExpr(); - return [=] { return Cond().getValue() ? L() : R(); }; + Expr r = readExpr(); + return [=] { return cond().getValue() ? l() : r(); }; } Expr ScriptParser::readParenExpr() { expect("("); - Expr E = readExpr(); + Expr e = readExpr(); expect(")"); - return E; + return e; } std::vector ScriptParser::readOutputSectionPhdrs() { - std::vector Phdrs; + std::vector phdrs; while (!errorCount() && peek().startswith(":")) { - StringRef Tok = next(); - Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); + StringRef tok = next(); + phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1)); } - return Phdrs; + return phdrs; } // Read a program header type name. The next token must be a // name of a program header type or a constant (e.g. "0x3"). unsigned ScriptParser::readPhdrType() { - StringRef Tok = next(); - if (Optional Val = parseInt(Tok)) - return *Val; + StringRef tok = next(); + if (Optional val = parseInt(tok)) + return *val; - unsigned Ret = StringSwitch(Tok) + unsigned ret = StringSwitch(tok) .Case("PT_NULL", PT_NULL) .Case("PT_LOAD", PT_LOAD) .Case("PT_DYNAMIC", PT_DYNAMIC) @@ -1330,56 +1330,56 @@ .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) .Default(-1); - if (Ret == (unsigned)-1) { - setError("invalid program header type: " + Tok); + if (ret == (unsigned)-1) { + setError("invalid program header type: " + tok); return PT_NULL; } - return Ret; + return ret; } // Reads an anonymous version declaration. void ScriptParser::readAnonymousDeclaration() { - std::vector Locals; - std::vector Globals; - std::tie(Locals, Globals) = readSymbols(); - - for (SymbolVersion V : Locals) { - if (V.Name == "*") - Config->DefaultSymbolVersion = VER_NDX_LOCAL; + std::vector locals; + std::vector globals; + std::tie(locals, globals) = readSymbols(); + + for (SymbolVersion v : locals) { + if (v.name == "*") + config->defaultSymbolVersion = VER_NDX_LOCAL; else - Config->VersionScriptLocals.push_back(V); + config->versionScriptLocals.push_back(v); } - for (SymbolVersion V : Globals) - Config->VersionScriptGlobals.push_back(V); + for (SymbolVersion v : globals) + config->versionScriptGlobals.push_back(v); expect(";"); } // Reads a non-anonymous version definition, // e.g. "VerStr { global: foo; bar; local: *; };". -void ScriptParser::readVersionDeclaration(StringRef VerStr) { +void ScriptParser::readVersionDeclaration(StringRef verStr) { // Read a symbol list. - std::vector Locals; - std::vector Globals; - std::tie(Locals, Globals) = readSymbols(); - - for (SymbolVersion V : Locals) { - if (V.Name == "*") - Config->DefaultSymbolVersion = VER_NDX_LOCAL; + std::vector locals; + std::vector globals; + std::tie(locals, globals) = readSymbols(); + + for (SymbolVersion v : locals) { + if (v.name == "*") + config->defaultSymbolVersion = VER_NDX_LOCAL; else - Config->VersionScriptLocals.push_back(V); + config->versionScriptLocals.push_back(v); } // Create a new version definition and add that to the global symbols. - VersionDefinition Ver; - Ver.Name = VerStr; - Ver.Globals = Globals; + VersionDefinition ver; + ver.name = verStr; + ver.globals = globals; // User-defined version number starts from 2 because 0 and 1 are // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively. - Ver.Id = Config->VersionDefinitions.size() + 2; - Config->VersionDefinitions.push_back(Ver); + ver.id = config->versionDefinitions.size() + 2; + config->versionDefinitions.push_back(ver); // Each version may have a parent version. For example, "Ver2" // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1" @@ -1391,39 +1391,39 @@ expect(";"); } -static bool hasWildcard(StringRef S) { - return S.find_first_of("?*[") != StringRef::npos; +static bool hasWildcard(StringRef s) { + return s.find_first_of("?*[") != StringRef::npos; } // Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };". std::pair, std::vector> ScriptParser::readSymbols() { - std::vector Locals; - std::vector Globals; - std::vector *V = &Globals; + std::vector locals; + std::vector globals; + std::vector *v = &globals; while (!errorCount()) { if (consume("}")) break; if (consumeLabel("local")) { - V = &Locals; + v = &locals; continue; } if (consumeLabel("global")) { - V = &Globals; + v = &globals; continue; } if (consume("extern")) { - std::vector Ext = readVersionExtern(); - V->insert(V->end(), Ext.begin(), Ext.end()); + std::vector ext = readVersionExtern(); + v->insert(v->end(), ext.begin(), ext.end()); } else { - StringRef Tok = next(); - V->push_back({unquote(Tok), false, hasWildcard(Tok)}); + StringRef tok = next(); + v->push_back({unquote(tok), false, hasWildcard(tok)}); } expect(";"); } - return {Locals, Globals}; + return {locals, globals}; } // Reads an "extern C++" directive, e.g., @@ -1432,30 +1432,30 @@ // The last semicolon is optional. E.g. this is OK: // "extern "C++" { ns::*; "f(int, double)" };" std::vector ScriptParser::readVersionExtern() { - StringRef Tok = next(); - bool IsCXX = Tok == "\"C++\""; - if (!IsCXX && Tok != "\"C\"") + StringRef tok = next(); + bool isCXX = tok == "\"C++\""; + if (!isCXX && tok != "\"C\"") setError("Unknown language"); expect("{"); - std::vector Ret; + std::vector ret; while (!errorCount() && peek() != "}") { - StringRef Tok = next(); - Ret.push_back( - {unquote(Tok), IsCXX, !Tok.startswith("\"") && hasWildcard(Tok)}); + StringRef tok = next(); + ret.push_back( + {unquote(tok), isCXX, !tok.startswith("\"") && hasWildcard(tok)}); if (consume("}")) - return Ret; + return ret; expect(";"); } expect("}"); - return Ret; + return ret; } -uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, - StringRef S3) { - if (!consume(S1) && !consume(S2) && !consume(S3)) { - setError("expected one of: " + S1 + ", " + S2 + ", or " + S3); +uint64_t ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2, + StringRef s3) { + if (!consume(s1) && !consume(s2) && !consume(s3)) { + setError("expected one of: " + s1 + ", " + s2 + ", or " + s3); return 0; } expect("="); @@ -1469,28 +1469,28 @@ void ScriptParser::readMemory() { expect("{"); while (!errorCount() && !consume("}")) { - StringRef Tok = next(); - if (Tok == "INCLUDE") { + StringRef tok = next(); + if (tok == "INCLUDE") { readInclude(); continue; } - uint32_t Flags = 0; - uint32_t NegFlags = 0; + uint32_t flags = 0; + uint32_t negFlags = 0; if (consume("(")) { - std::tie(Flags, NegFlags) = readMemoryAttributes(); + std::tie(flags, negFlags) = readMemoryAttributes(); expect(")"); } expect(":"); - uint64_t Origin = readMemoryAssignment("ORIGIN", "org", "o"); + uint64_t origin = readMemoryAssignment("ORIGIN", "org", "o"); expect(","); - uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); + uint64_t length = readMemoryAssignment("LENGTH", "len", "l"); // Add the memory region to the region map. - MemoryRegion *MR = make(Tok, Origin, Length, Flags, NegFlags); - if (!Script->MemoryRegions.insert({Tok, MR}).second) - setError("region '" + Tok + "' already defined"); + MemoryRegion *mr = make(tok, origin, length, flags, negFlags); + if (!script->memoryRegions.insert({tok, mr}).second) + setError("region '" + tok + "' already defined"); } } @@ -1498,43 +1498,43 @@ // flags when placing output sections in a memory region. These flags // are only used when an explicit memory region name is not used. std::pair ScriptParser::readMemoryAttributes() { - uint32_t Flags = 0; - uint32_t NegFlags = 0; - bool Invert = false; - - for (char C : next().lower()) { - uint32_t Flag = 0; - if (C == '!') - Invert = !Invert; - else if (C == 'w') - Flag = SHF_WRITE; - else if (C == 'x') - Flag = SHF_EXECINSTR; - else if (C == 'a') - Flag = SHF_ALLOC; - else if (C != 'r') + uint32_t flags = 0; + uint32_t negFlags = 0; + bool invert = false; + + for (char c : next().lower()) { + uint32_t flag = 0; + if (c == '!') + invert = !invert; + else if (c == 'w') + flag = SHF_WRITE; + else if (c == 'x') + flag = SHF_EXECINSTR; + else if (c == 'a') + flag = SHF_ALLOC; + else if (c != 'r') setError("invalid memory region attribute"); - if (Invert) - NegFlags |= Flag; + if (invert) + negFlags |= flag; else - Flags |= Flag; + flags |= flag; } - return {Flags, NegFlags}; + return {flags, negFlags}; } -void elf::readLinkerScript(MemoryBufferRef MB) { - ScriptParser(MB).readLinkerScript(); +void elf::readLinkerScript(MemoryBufferRef mb) { + ScriptParser(mb).readLinkerScript(); } -void elf::readVersionScript(MemoryBufferRef MB) { - ScriptParser(MB).readVersionScript(); +void elf::readVersionScript(MemoryBufferRef mb) { + ScriptParser(mb).readVersionScript(); } -void elf::readDynamicList(MemoryBufferRef MB) { - ScriptParser(MB).readDynamicList(); +void elf::readDynamicList(MemoryBufferRef mb) { + ScriptParser(mb).readDynamicList(); } -void elf::readDefsym(StringRef Name, MemoryBufferRef MB) { - ScriptParser(MB).readDefsym(Name); +void elf::readDefsym(StringRef name, MemoryBufferRef mb) { + ScriptParser(mb).readDefsym(name); } Index: lld/trunk/ELF/SymbolTable.h =================================================================== --- lld/trunk/ELF/SymbolTable.h +++ lld/trunk/ELF/SymbolTable.h @@ -33,41 +33,41 @@ // is one add* function per symbol type. class SymbolTable { public: - void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); + void wrap(Symbol *sym, Symbol *real, Symbol *wrap); - void forEachSymbol(llvm::function_ref Fn) { - for (Symbol *Sym : SymVector) - if (!Sym->isPlaceholder()) - Fn(Sym); + void forEachSymbol(llvm::function_ref fn) { + for (Symbol *sym : symVector) + if (!sym->isPlaceholder()) + fn(sym); } - Symbol *insert(StringRef Name); + Symbol *insert(StringRef name); Symbol *addSymbol(const Symbol &New); void scanVersionScript(); - Symbol *find(StringRef Name); + Symbol *find(StringRef name); void handleDynamicList(); // Set of .so files to not link the same shared object file more than once. - llvm::DenseMap SoNames; + llvm::DenseMap soNames; // Comdat groups define "link once" sections. If two comdat groups have the // same name, only one of them is linked, and the other is ignored. This map // is used to uniquify them. - llvm::DenseMap ComdatGroups; + llvm::DenseMap comdatGroups; private: - std::vector findByVersion(SymbolVersion Ver); - std::vector findAllByVersion(SymbolVersion Ver); + std::vector findByVersion(SymbolVersion ver); + std::vector findAllByVersion(SymbolVersion ver); llvm::StringMap> &getDemangledSyms(); void handleAnonymousVersion(); - void assignExactVersion(SymbolVersion Ver, uint16_t VersionId, - StringRef VersionName); - void assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId); + void assignExactVersion(SymbolVersion ver, uint16_t versionId, + StringRef versionName); + void assignWildcardVersion(SymbolVersion ver, uint16_t versionId); // The order the global symbols are in is not defined. We can use an arbitrary // order, but it has to be reproducible. That is true even when cross linking. @@ -76,17 +76,17 @@ // but a bit inefficient. // FIXME: Experiment with passing in a custom hashing or sorting the symbols // once symbol resolution is finished. - llvm::DenseMap SymMap; - std::vector SymVector; + llvm::DenseMap symMap; + std::vector symVector; // A map from demangled symbol names to their symbol objects. // This mapping is 1:N because two symbols with different versions // can have the same name. We use this map to handle "extern C++ {}" // directive in version scripts. - llvm::Optional>> DemangledSyms; + llvm::Optional>> demangledSyms; }; -extern SymbolTable *Symtab; +extern SymbolTable *symtab; } // namespace elf } // namespace lld Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -30,73 +30,73 @@ using namespace lld; using namespace lld::elf; -SymbolTable *elf::Symtab; +SymbolTable *elf::symtab; -void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { +void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { // Swap symbols as instructed by -wrap. - int &Idx1 = SymMap[CachedHashStringRef(Sym->getName())]; - int &Idx2 = SymMap[CachedHashStringRef(Real->getName())]; - int &Idx3 = SymMap[CachedHashStringRef(Wrap->getName())]; + int &idx1 = symMap[CachedHashStringRef(sym->getName())]; + int &idx2 = symMap[CachedHashStringRef(real->getName())]; + int &idx3 = symMap[CachedHashStringRef(wrap->getName())]; - Idx2 = Idx1; - Idx1 = Idx3; + idx2 = idx1; + idx1 = idx3; // Now renaming is complete. No one refers Real symbol. We could leave // Real as-is, but if Real is written to the symbol table, that may // contain irrelevant values. So, we copy all values from Sym to Real. - StringRef S = Real->getName(); - memcpy(Real, Sym, sizeof(SymbolUnion)); - Real->setName(S); + StringRef s = real->getName(); + memcpy(real, sym, sizeof(SymbolUnion)); + real->setName(s); } // Find an existing symbol or create a new one. -Symbol *SymbolTable::insert(StringRef Name) { +Symbol *SymbolTable::insert(StringRef name) { // @@ means the symbol is the default version. In that // case @@ will be used to resolve references to . // // Since this is a hot path, the following string search code is // optimized for speed. StringRef::find(char) is much faster than // StringRef::find(StringRef). - size_t Pos = Name.find('@'); - if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@') - Name = Name.take_front(Pos); - - auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); - int &SymIndex = P.first->second; - bool IsNew = P.second; - - if (!IsNew) - return SymVector[SymIndex]; - - Symbol *Sym = reinterpret_cast(make()); - SymVector.push_back(Sym); - - Sym->setName(Name); - Sym->SymbolKind = Symbol::PlaceholderKind; - Sym->VersionId = Config->DefaultSymbolVersion; - Sym->Visibility = STV_DEFAULT; - Sym->IsUsedInRegularObj = false; - Sym->ExportDynamic = false; - Sym->CanInline = true; - Sym->ScriptDefined = false; - Sym->Partition = 1; - return Sym; + size_t pos = name.find('@'); + if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@') + name = name.take_front(pos); + + auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()}); + int &symIndex = p.first->second; + bool isNew = p.second; + + if (!isNew) + return symVector[symIndex]; + + Symbol *sym = reinterpret_cast(make()); + symVector.push_back(sym); + + sym->setName(name); + sym->symbolKind = Symbol::PlaceholderKind; + sym->versionId = config->defaultSymbolVersion; + sym->visibility = STV_DEFAULT; + sym->isUsedInRegularObj = false; + sym->exportDynamic = false; + sym->canInline = true; + sym->scriptDefined = false; + sym->partition = 1; + return sym; } Symbol *SymbolTable::addSymbol(const Symbol &New) { - Symbol *Sym = Symtab->insert(New.getName()); - Sym->resolve(New); - return Sym; + Symbol *sym = symtab->insert(New.getName()); + sym->resolve(New); + return sym; } -Symbol *SymbolTable::find(StringRef Name) { - auto It = SymMap.find(CachedHashStringRef(Name)); - if (It == SymMap.end()) +Symbol *SymbolTable::find(StringRef name) { + auto it = symMap.find(CachedHashStringRef(name)); + if (it == symMap.end()) return nullptr; - Symbol *Sym = SymVector[It->second]; - if (Sym->isPlaceholder()) + Symbol *sym = symVector[it->second]; + if (sym->isPlaceholder()) return nullptr; - return Sym; + return sym; } // Initialize DemangledSyms with a map from demangled symbols to symbol @@ -113,119 +113,119 @@ // So, if "extern C++" feature is used, we need to demangle all known // symbols. StringMap> &SymbolTable::getDemangledSyms() { - if (!DemangledSyms) { - DemangledSyms.emplace(); - for (Symbol *Sym : SymVector) { - if (!Sym->isDefined() && !Sym->isCommon()) + if (!demangledSyms) { + demangledSyms.emplace(); + for (Symbol *sym : symVector) { + if (!sym->isDefined() && !sym->isCommon()) continue; - if (Optional S = demangleItanium(Sym->getName())) - (*DemangledSyms)[*S].push_back(Sym); + if (Optional s = demangleItanium(sym->getName())) + (*demangledSyms)[*s].push_back(sym); else - (*DemangledSyms)[Sym->getName()].push_back(Sym); + (*demangledSyms)[sym->getName()].push_back(sym); } } - return *DemangledSyms; + return *demangledSyms; } -std::vector SymbolTable::findByVersion(SymbolVersion Ver) { - if (Ver.IsExternCpp) - return getDemangledSyms().lookup(Ver.Name); - if (Symbol *B = find(Ver.Name)) - if (B->isDefined() || B->isCommon()) - return {B}; +std::vector SymbolTable::findByVersion(SymbolVersion ver) { + if (ver.isExternCpp) + return getDemangledSyms().lookup(ver.name); + if (Symbol *b = find(ver.name)) + if (b->isDefined() || b->isCommon()) + return {b}; return {}; } -std::vector SymbolTable::findAllByVersion(SymbolVersion Ver) { - std::vector Res; - StringMatcher M(Ver.Name); - - if (Ver.IsExternCpp) { - for (auto &P : getDemangledSyms()) - if (M.match(P.first())) - Res.insert(Res.end(), P.second.begin(), P.second.end()); - return Res; +std::vector SymbolTable::findAllByVersion(SymbolVersion ver) { + std::vector res; + StringMatcher m(ver.name); + + if (ver.isExternCpp) { + for (auto &p : getDemangledSyms()) + if (m.match(p.first())) + res.insert(res.end(), p.second.begin(), p.second.end()); + return res; } - for (Symbol *Sym : SymVector) - if ((Sym->isDefined() || Sym->isCommon()) && M.match(Sym->getName())) - Res.push_back(Sym); - return Res; + for (Symbol *sym : symVector) + if ((sym->isDefined() || sym->isCommon()) && m.match(sym->getName())) + res.push_back(sym); + return res; } // If there's only one anonymous version definition in a version // script file, the script does not actually define any symbol version, // but just specifies symbols visibilities. void SymbolTable::handleAnonymousVersion() { - for (SymbolVersion &Ver : Config->VersionScriptGlobals) - assignExactVersion(Ver, VER_NDX_GLOBAL, "global"); - for (SymbolVersion &Ver : Config->VersionScriptGlobals) - assignWildcardVersion(Ver, VER_NDX_GLOBAL); - for (SymbolVersion &Ver : Config->VersionScriptLocals) - assignExactVersion(Ver, VER_NDX_LOCAL, "local"); - for (SymbolVersion &Ver : Config->VersionScriptLocals) - assignWildcardVersion(Ver, VER_NDX_LOCAL); + for (SymbolVersion &ver : config->versionScriptGlobals) + assignExactVersion(ver, VER_NDX_GLOBAL, "global"); + for (SymbolVersion &ver : config->versionScriptGlobals) + assignWildcardVersion(ver, VER_NDX_GLOBAL); + for (SymbolVersion &ver : config->versionScriptLocals) + assignExactVersion(ver, VER_NDX_LOCAL, "local"); + for (SymbolVersion &ver : config->versionScriptLocals) + assignWildcardVersion(ver, VER_NDX_LOCAL); } // Handles -dynamic-list. void SymbolTable::handleDynamicList() { - for (SymbolVersion &Ver : Config->DynamicList) { - std::vector Syms; - if (Ver.HasWildcard) - Syms = findAllByVersion(Ver); + for (SymbolVersion &ver : config->dynamicList) { + std::vector syms; + if (ver.hasWildcard) + syms = findAllByVersion(ver); else - Syms = findByVersion(Ver); + syms = findByVersion(ver); - for (Symbol *B : Syms) { - if (!Config->Shared) - B->ExportDynamic = true; - else if (B->includeInDynsym()) - B->IsPreemptible = true; + for (Symbol *b : syms) { + if (!config->shared) + b->exportDynamic = true; + else if (b->includeInDynsym()) + b->isPreemptible = true; } } } // Set symbol versions to symbols. This function handles patterns // containing no wildcard characters. -void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId, - StringRef VersionName) { - if (Ver.HasWildcard) +void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, + StringRef versionName) { + if (ver.hasWildcard) return; // Get a list of symbols which we need to assign the version to. - std::vector Syms = findByVersion(Ver); - if (Syms.empty()) { - if (!Config->UndefinedVersion) - error("version script assignment of '" + VersionName + "' to symbol '" + - Ver.Name + "' failed: symbol not defined"); + std::vector syms = findByVersion(ver); + if (syms.empty()) { + if (!config->undefinedVersion) + error("version script assignment of '" + versionName + "' to symbol '" + + ver.name + "' failed: symbol not defined"); return; } // Assign the version. - for (Symbol *Sym : Syms) { + for (Symbol *sym : syms) { // Skip symbols containing version info because symbol versions // specified by symbol names take precedence over version scripts. // See parseSymbolVersion(). - if (Sym->getName().contains('@')) + if (sym->getName().contains('@')) continue; - if (Sym->VersionId != Config->DefaultSymbolVersion && - Sym->VersionId != VersionId) - error("duplicate symbol '" + Ver.Name + "' in version script"); - Sym->VersionId = VersionId; + if (sym->versionId != config->defaultSymbolVersion && + sym->versionId != versionId) + error("duplicate symbol '" + ver.name + "' in version script"); + sym->versionId = versionId; } } -void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) { - if (!Ver.HasWildcard) +void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) { + if (!ver.hasWildcard) return; // Exact matching takes precendence over fuzzy matching, // so we set a version to a symbol only if no version has been assigned // to the symbol. This behavior is compatible with GNU. - for (Symbol *B : findAllByVersion(Ver)) - if (B->VersionId == Config->DefaultSymbolVersion) - B->VersionId = VersionId; + for (Symbol *b : findAllByVersion(ver)) + if (b->versionId == config->defaultSymbolVersion) + b->versionId = versionId; } // This function processes version scripts by updating VersionId @@ -241,21 +241,21 @@ // First, we assign versions to exact matching symbols, // i.e. version definitions not containing any glob meta-characters. - for (VersionDefinition &V : Config->VersionDefinitions) - for (SymbolVersion &Ver : V.Globals) - assignExactVersion(Ver, V.Id, V.Name); + for (VersionDefinition &v : config->versionDefinitions) + for (SymbolVersion &ver : v.globals) + assignExactVersion(ver, v.id, v.name); // Next, we assign versions to fuzzy matching symbols, // i.e. version definitions containing glob meta-characters. // Note that because the last match takes precedence over previous matches, // we iterate over the definitions in the reverse order. - for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions)) - for (SymbolVersion &Ver : V.Globals) - assignWildcardVersion(Ver, V.Id); + for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) + for (SymbolVersion &ver : v.globals) + assignWildcardVersion(ver, v.id); // Symbol themselves might know their versions because symbols // can contain versions in the form of @. // Let them parse and update their names to exclude version suffix. - for (Symbol *Sym : SymVector) - Sym->parseSymbolVersion(); + for (Symbol *sym : symVector) + sym->parseSymbolVersion(); } Index: lld/trunk/ELF/Symbols.h =================================================================== --- lld/trunk/ELF/Symbols.h +++ lld/trunk/ELF/Symbols.h @@ -44,11 +44,11 @@ // and the linker doesn't use local symbol names for name resolution. So, we // use this class to represents strings read from string tables. struct StringRefZ { - StringRefZ(const char *S) : Data(S), Size(-1) {} - StringRefZ(StringRef S) : Data(S.data()), Size(S.size()) {} + StringRefZ(const char *s) : data(s), size(-1) {} + StringRefZ(StringRef s) : data(s.data()), size(s.size()) {} - const char *Data; - const uint32_t Size; + const char *data; + const uint32_t size; }; // The base class for real symbol classes. @@ -64,84 +64,84 @@ LazyObjectKind, }; - Kind kind() const { return static_cast(SymbolKind); } + Kind kind() const { return static_cast(symbolKind); } // The file from which this symbol was created. - InputFile *File; + InputFile *file; protected: - const char *NameData; - mutable uint32_t NameSize; + const char *nameData; + mutable uint32_t nameSize; public: - uint32_t DynsymIndex = 0; - uint32_t GotIndex = -1; - uint32_t PltIndex = -1; + uint32_t dynsymIndex = 0; + uint32_t gotIndex = -1; + uint32_t pltIndex = -1; - uint32_t GlobalDynIndex = -1; + uint32_t globalDynIndex = -1; // This field is a index to the symbol's version definition. - uint32_t VerdefIndex = -1; + uint32_t verdefIndex = -1; // Version definition index. - uint16_t VersionId; + uint16_t versionId; // An index into the .branch_lt section on PPC64. - uint16_t PPC64BranchltIndex = -1; + uint16_t ppc64BranchltIndex = -1; // Symbol binding. This is not overwritten by replace() to track // changes during resolution. In particular: // - An undefined weak is still weak when it resolves to a shared library. // - An undefined weak will not fetch archive members, but we have to // remember it is weak. - uint8_t Binding; + uint8_t binding; // The following fields have the same meaning as the ELF symbol attributes. - uint8_t Type; // symbol type - uint8_t StOther; // st_other field value + uint8_t type; // symbol type + uint8_t stOther; // st_other field value - uint8_t SymbolKind; + uint8_t symbolKind; // Symbol visibility. This is the computed minimum visibility of all // observed non-DSO symbols. - unsigned Visibility : 2; + unsigned visibility : 2; // True if the symbol was used for linking and thus need to be added to the // output file's symbol table. This is true for all symbols except for // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that // are unreferenced except by other bitcode objects. - unsigned IsUsedInRegularObj : 1; + unsigned isUsedInRegularObj : 1; // If this flag is true and the symbol has protected or default visibility, it // will appear in .dynsym. This flag is set by interposable DSO symbols in // executables, by most symbols in DSOs and executables built with // --export-dynamic, and by dynamic lists. - unsigned ExportDynamic : 1; + unsigned exportDynamic : 1; // False if LTO shouldn't inline whatever this symbol points to. If a symbol // is overwritten after LTO, LTO shouldn't inline the symbol because it // doesn't know the final contents of the symbol. - unsigned CanInline : 1; + unsigned canInline : 1; // True if this symbol is specified by --trace-symbol option. - unsigned Traced : 1; + unsigned traced : 1; inline void replace(const Symbol &New); bool includeInDynsym() const; uint8_t computeBinding() const; - bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } + bool isWeak() const { return binding == llvm::ELF::STB_WEAK; } - bool isUndefined() const { return SymbolKind == UndefinedKind; } - bool isCommon() const { return SymbolKind == CommonKind; } - bool isDefined() const { return SymbolKind == DefinedKind; } - bool isShared() const { return SymbolKind == SharedKind; } - bool isPlaceholder() const { return SymbolKind == PlaceholderKind; } + bool isUndefined() const { return symbolKind == UndefinedKind; } + bool isCommon() const { return symbolKind == CommonKind; } + bool isDefined() const { return symbolKind == DefinedKind; } + bool isShared() const { return symbolKind == SharedKind; } + bool isPlaceholder() const { return symbolKind == PlaceholderKind; } - bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; } + bool isLocal() const { return binding == llvm::ELF::STB_LOCAL; } bool isLazy() const { - return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; + return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind; } // True if this is an undefined weak symbol. This only works once @@ -152,23 +152,23 @@ } StringRef getName() const { - if (NameSize == (uint32_t)-1) - NameSize = strlen(NameData); - return {NameData, NameSize}; + if (nameSize == (uint32_t)-1) + nameSize = strlen(nameData); + return {nameData, nameSize}; } - void setName(StringRef S) { - NameData = S.data(); - NameSize = S.size(); + void setName(StringRef s) { + nameData = s.data(); + nameSize = s.size(); } void parseSymbolVersion(); - bool isInGot() const { return GotIndex != -1U; } - bool isInPlt() const { return PltIndex != -1U; } - bool isInPPC64Branchlt() const { return PPC64BranchltIndex != 0xffff; } + bool isInGot() const { return gotIndex != -1U; } + bool isInPlt() const { return pltIndex != -1U; } + bool isInPPC64Branchlt() const { return ppc64BranchltIndex != 0xffff; } - uint64_t getVA(int64_t Addend = 0) const; + uint64_t getVA(int64_t addend = 0) const; uint64_t getGotOffset() const; uint64_t getGotVA() const; @@ -193,8 +193,8 @@ // // For example, if "this" is an undefined symbol and a new symbol is // a defined symbol, "this" is replaced with the new symbol. - void mergeProperties(const Symbol &Other); - void resolve(const Symbol &Other); + void mergeProperties(const Symbol &other); + void resolve(const Symbol &other); // If this is a lazy symbol, fetch an input file and add the symbol // in the file to the symbol table. Calling this function on @@ -202,83 +202,83 @@ void fetch() const; private: - static bool isExportDynamic(Kind K, uint8_t Visibility) { - if (K == SharedKind) - return Visibility == llvm::ELF::STV_DEFAULT; - return Config->Shared || Config->ExportDynamic; + static bool isExportDynamic(Kind k, uint8_t visibility) { + if (k == SharedKind) + return visibility == llvm::ELF::STV_DEFAULT; + return config->shared || config->exportDynamic; } - void resolveUndefined(const Undefined &Other); - void resolveCommon(const CommonSymbol &Other); - void resolveDefined(const Defined &Other); - template void resolveLazy(const LazyT &Other); - void resolveShared(const SharedSymbol &Other); + void resolveUndefined(const Undefined &other); + void resolveCommon(const CommonSymbol &other); + void resolveDefined(const Defined &other); + template void resolveLazy(const LazyT &other); + void resolveShared(const SharedSymbol &other); - int compare(const Symbol *Other) const; + int compare(const Symbol *other) const; inline size_t getSymbolSize() const; protected: - Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding, - uint8_t StOther, uint8_t Type) - : File(File), NameData(Name.Data), NameSize(Name.Size), Binding(Binding), - Type(Type), StOther(StOther), SymbolKind(K), Visibility(StOther & 3), - IsUsedInRegularObj(!File || File->kind() == InputFile::ObjKind), - ExportDynamic(isExportDynamic(K, Visibility)), CanInline(false), - Traced(false), NeedsPltAddr(false), IsInIplt(false), GotInIgot(false), - IsPreemptible(false), Used(!Config->GcSections), NeedsTocRestore(false), - ScriptDefined(false) {} + Symbol(Kind k, InputFile *file, StringRefZ name, uint8_t binding, + uint8_t stOther, uint8_t type) + : file(file), nameData(name.data), nameSize(name.size), binding(binding), + type(type), stOther(stOther), symbolKind(k), visibility(stOther & 3), + isUsedInRegularObj(!file || file->kind() == InputFile::ObjKind), + exportDynamic(isExportDynamic(k, visibility)), canInline(false), + traced(false), needsPltAddr(false), isInIplt(false), gotInIgot(false), + isPreemptible(false), used(!config->gcSections), needsTocRestore(false), + scriptDefined(false) {} public: // True the symbol should point to its PLT entry. // For SharedSymbol only. - unsigned NeedsPltAddr : 1; + unsigned needsPltAddr : 1; // True if this symbol is in the Iplt sub-section of the Plt and the Igot // sub-section of the .got.plt or .got. - unsigned IsInIplt : 1; + unsigned isInIplt : 1; // True if this symbol needs a GOT entry and its GOT entry is actually in // Igot. This will be true only for certain non-preemptible ifuncs. - unsigned GotInIgot : 1; + unsigned gotInIgot : 1; // True if this symbol is preemptible at load time. - unsigned IsPreemptible : 1; + unsigned isPreemptible : 1; // True if an undefined or shared symbol is used from a live section. - unsigned Used : 1; + unsigned used : 1; // True if a call to this symbol needs to be followed by a restore of the // PPC64 toc pointer. - unsigned NeedsTocRestore : 1; + unsigned needsTocRestore : 1; // True if this symbol is defined by a linker script. - unsigned ScriptDefined : 1; + unsigned scriptDefined : 1; // The partition whose dynamic symbol table contains this symbol's definition. - uint8_t Partition = 1; + uint8_t partition = 1; - bool isSection() const { return Type == llvm::ELF::STT_SECTION; } - bool isTls() const { return Type == llvm::ELF::STT_TLS; } - bool isFunc() const { return Type == llvm::ELF::STT_FUNC; } - bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; } - bool isObject() const { return Type == llvm::ELF::STT_OBJECT; } - bool isFile() const { return Type == llvm::ELF::STT_FILE; } + bool isSection() const { return type == llvm::ELF::STT_SECTION; } + bool isTls() const { return type == llvm::ELF::STT_TLS; } + bool isFunc() const { return type == llvm::ELF::STT_FUNC; } + bool isGnuIFunc() const { return type == llvm::ELF::STT_GNU_IFUNC; } + bool isObject() const { return type == llvm::ELF::STT_OBJECT; } + bool isFile() const { return type == llvm::ELF::STT_FILE; } }; // Represents a symbol that is defined in the current output file. class Defined : public Symbol { public: - Defined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, - uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section) - : Symbol(DefinedKind, File, Name, Binding, StOther, Type), Value(Value), - Size(Size), Section(Section) {} - - static bool classof(const Symbol *S) { return S->isDefined(); } - - uint64_t Value; - uint64_t Size; - SectionBase *Section; + Defined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther, + uint8_t type, uint64_t value, uint64_t size, SectionBase *section) + : Symbol(DefinedKind, file, name, binding, stOther, type), value(value), + size(size), section(section) {} + + static bool classof(const Symbol *s) { return s->isDefined(); } + + uint64_t value; + uint64_t size; + SectionBase *section; }; // Represents a common symbol. @@ -304,40 +304,40 @@ // section. (Therefore, the later passes don't see any CommonSymbols.) class CommonSymbol : public Symbol { public: - CommonSymbol(InputFile *File, StringRefZ Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, uint64_t Alignment, uint64_t Size) - : Symbol(CommonKind, File, Name, Binding, StOther, Type), - Alignment(Alignment), Size(Size) {} + CommonSymbol(InputFile *file, StringRefZ name, uint8_t binding, + uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size) + : Symbol(CommonKind, file, name, binding, stOther, type), + alignment(alignment), size(size) {} - static bool classof(const Symbol *S) { return S->isCommon(); } + static bool classof(const Symbol *s) { return s->isCommon(); } - uint32_t Alignment; - uint64_t Size; + uint32_t alignment; + uint64_t size; }; class Undefined : public Symbol { public: - Undefined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther, - uint8_t Type, uint32_t DiscardedSecIdx = 0) - : Symbol(UndefinedKind, File, Name, Binding, StOther, Type), - DiscardedSecIdx(DiscardedSecIdx) {} + Undefined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther, + uint8_t type, uint32_t discardedSecIdx = 0) + : Symbol(UndefinedKind, file, name, binding, stOther, type), + discardedSecIdx(discardedSecIdx) {} - static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } + static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; } // The section index if in a discarded section, 0 otherwise. - uint32_t DiscardedSecIdx; + uint32_t discardedSecIdx; }; class SharedSymbol : public Symbol { public: - static bool classof(const Symbol *S) { return S->kind() == SharedKind; } + static bool classof(const Symbol *s) { return s->kind() == SharedKind; } - SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, - uint32_t Alignment, uint32_t VerdefIndex) - : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value), - Size(Size), Alignment(Alignment) { - this->VerdefIndex = VerdefIndex; + SharedSymbol(InputFile &file, StringRef name, uint8_t binding, + uint8_t stOther, uint8_t type, uint64_t value, uint64_t size, + uint32_t alignment, uint32_t verdefIndex) + : Symbol(SharedKind, &file, name, binding, stOther, type), value(value), + size(size), alignment(alignment) { + this->verdefIndex = verdefIndex; // GNU ifunc is a mechanism to allow user-supplied functions to // resolve PLT slot values at load-time. This is contrary to the // regular symbol resolution scheme in which symbols are resolved just @@ -354,20 +354,20 @@ // For DSO symbols, we always call them through PLT slots anyway. // So there's no difference between GNU ifunc and regular function // symbols if they are in DSOs. So we can handle GNU_IFUNC as FUNC. - if (this->Type == llvm::ELF::STT_GNU_IFUNC) - this->Type = llvm::ELF::STT_FUNC; + if (this->type == llvm::ELF::STT_GNU_IFUNC) + this->type = llvm::ELF::STT_FUNC; } - SharedFile &getFile() const { return *cast(File); } + SharedFile &getFile() const { return *cast(file); } - uint64_t Value; // st_value - uint64_t Size; // st_size - uint32_t Alignment; + uint64_t value; // st_value + uint64_t size; // st_size + uint32_t alignment; // This is true if there has been at least one undefined reference to the // symbol. The binding may change to STB_WEAK if the first undefined reference // is weak. - bool Referenced = false; + bool referenced = false; }; // LazyArchive and LazyObject represent a symbols that is not yet in the link, @@ -386,78 +386,78 @@ // symbol. class LazyArchive : public Symbol { public: - LazyArchive(InputFile &File, const llvm::object::Archive::Symbol S) - : Symbol(LazyArchiveKind, &File, S.getName(), llvm::ELF::STB_GLOBAL, + LazyArchive(InputFile &file, const llvm::object::Archive::Symbol s) + : Symbol(LazyArchiveKind, &file, s.getName(), llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE), - Sym(S) {} + sym(s) {} - static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; } + static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; } MemoryBufferRef getMemberBuffer(); - const llvm::object::Archive::Symbol Sym; + const llvm::object::Archive::Symbol sym; }; // LazyObject symbols represents symbols in object files between // --start-lib and --end-lib options. class LazyObject : public Symbol { public: - LazyObject(InputFile &File, StringRef Name) - : Symbol(LazyObjectKind, &File, Name, llvm::ELF::STB_GLOBAL, + LazyObject(InputFile &file, StringRef name) + : Symbol(LazyObjectKind, &file, name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE) {} - static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; } + static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; } }; // Some linker-generated symbols need to be created as // Defined symbols. struct ElfSym { // __bss_start - static Defined *Bss; + static Defined *bss; // etext and _etext - static Defined *Etext1; - static Defined *Etext2; + static Defined *etext1; + static Defined *etext2; // edata and _edata - static Defined *Edata1; - static Defined *Edata2; + static Defined *edata1; + static Defined *edata2; // end and _end - static Defined *End1; - static Defined *End2; + static Defined *end1; + static Defined *end2; // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to // be at some offset from the base of the .got section, usually 0 or // the end of the .got. - static Defined *GlobalOffsetTable; + static Defined *globalOffsetTable; // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. - static Defined *MipsGp; - static Defined *MipsGpDisp; - static Defined *MipsLocalGp; + static Defined *mipsGp; + static Defined *mipsGpDisp; + static Defined *mipsLocalGp; // __rel{,a}_iplt_{start,end} symbols. - static Defined *RelaIpltStart; - static Defined *RelaIpltEnd; + static Defined *relaIpltStart; + static Defined *relaIpltEnd; // __global_pointer$ for RISC-V. - static Defined *RISCVGlobalPointer; + static Defined *riscvGlobalPointer; // _TLS_MODULE_BASE_ on targets that support TLSDESC. - static Defined *TlsModuleBase; + static Defined *tlsModuleBase; }; // A buffer class that is large enough to hold any Symbol-derived // object. We allocate memory using this class and instantiate a symbol // using the placement new. union SymbolUnion { - alignas(Defined) char A[sizeof(Defined)]; - alignas(CommonSymbol) char B[sizeof(CommonSymbol)]; - alignas(Undefined) char C[sizeof(Undefined)]; - alignas(SharedSymbol) char D[sizeof(SharedSymbol)]; - alignas(LazyArchive) char E[sizeof(LazyArchive)]; - alignas(LazyObject) char F[sizeof(LazyObject)]; + alignas(Defined) char a[sizeof(Defined)]; + alignas(CommonSymbol) char b[sizeof(CommonSymbol)]; + alignas(Undefined) char c[sizeof(Undefined)]; + alignas(SharedSymbol) char d[sizeof(SharedSymbol)]; + alignas(LazyArchive) char e[sizeof(LazyArchive)]; + alignas(LazyObject) char f[sizeof(LazyObject)]; }; // It is important to keep the size of SymbolUnion small for performance and @@ -482,7 +482,7 @@ AssertSymbol(); } -void printTraceSymbol(const Symbol *Sym); +void printTraceSymbol(const Symbol *sym); size_t Symbol::getSymbolSize() const { switch (kind()) { @@ -515,39 +515,39 @@ // non-TLS relocations, so there's a clear distinction between TLS // and non-TLS symbols. It is an error if the same symbol is defined // as a TLS symbol in one file and as a non-TLS symbol in other file. - if (SymbolKind != PlaceholderKind && !isLazy() && !New.isLazy()) { - bool TlsMismatch = (Type == STT_TLS && New.Type != STT_TLS) || - (Type != STT_TLS && New.Type == STT_TLS); - if (TlsMismatch) + if (symbolKind != PlaceholderKind && !isLazy() && !New.isLazy()) { + bool tlsMismatch = (type == STT_TLS && New.type != STT_TLS) || + (type != STT_TLS && New.type == STT_TLS); + if (tlsMismatch) error("TLS attribute mismatch: " + toString(*this) + "\n>>> defined in " + - toString(New.File) + "\n>>> defined in " + toString(File)); + toString(New.file) + "\n>>> defined in " + toString(file)); } - Symbol Old = *this; + Symbol old = *this; memcpy(this, &New, New.getSymbolSize()); - VersionId = Old.VersionId; - Visibility = Old.Visibility; - IsUsedInRegularObj = Old.IsUsedInRegularObj; - ExportDynamic = Old.ExportDynamic; - CanInline = Old.CanInline; - Traced = Old.Traced; - IsPreemptible = Old.IsPreemptible; - ScriptDefined = Old.ScriptDefined; - Partition = Old.Partition; + versionId = old.versionId; + visibility = old.visibility; + isUsedInRegularObj = old.isUsedInRegularObj; + exportDynamic = old.exportDynamic; + canInline = old.canInline; + traced = old.traced; + isPreemptible = old.isPreemptible; + scriptDefined = old.scriptDefined; + partition = old.partition; // Symbol length is computed lazily. If we already know a symbol length, // propagate it. - if (NameData == Old.NameData && NameSize == 0 && Old.NameSize != 0) - NameSize = Old.NameSize; + if (nameData == old.nameData && nameSize == 0 && old.nameSize != 0) + nameSize = old.nameSize; // Print out a log message if --trace-symbol was specified. // This is for debugging. - if (Traced) + if (traced) printTraceSymbol(this); } -void maybeWarnUnorderableSymbol(const Symbol *Sym); +void maybeWarnUnorderableSymbol(const Symbol *sym); } // namespace elf } // namespace lld Index: lld/trunk/ELF/Symbols.cpp =================================================================== --- lld/trunk/ELF/Symbols.cpp +++ lld/trunk/ELF/Symbols.cpp @@ -26,36 +26,36 @@ using namespace lld; using namespace lld::elf; -Defined *ElfSym::Bss; -Defined *ElfSym::Etext1; -Defined *ElfSym::Etext2; -Defined *ElfSym::Edata1; -Defined *ElfSym::Edata2; -Defined *ElfSym::End1; -Defined *ElfSym::End2; -Defined *ElfSym::GlobalOffsetTable; -Defined *ElfSym::MipsGp; -Defined *ElfSym::MipsGpDisp; -Defined *ElfSym::MipsLocalGp; -Defined *ElfSym::RelaIpltStart; -Defined *ElfSym::RelaIpltEnd; -Defined *ElfSym::RISCVGlobalPointer; -Defined *ElfSym::TlsModuleBase; +Defined *ElfSym::bss; +Defined *ElfSym::etext1; +Defined *ElfSym::etext2; +Defined *ElfSym::edata1; +Defined *ElfSym::edata2; +Defined *ElfSym::end1; +Defined *ElfSym::end2; +Defined *ElfSym::globalOffsetTable; +Defined *ElfSym::mipsGp; +Defined *ElfSym::mipsGpDisp; +Defined *ElfSym::mipsLocalGp; +Defined *ElfSym::relaIpltStart; +Defined *ElfSym::relaIpltEnd; +Defined *ElfSym::riscvGlobalPointer; +Defined *ElfSym::tlsModuleBase; -static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { - switch (Sym.kind()) { +static uint64_t getSymVA(const Symbol &sym, int64_t &addend) { + switch (sym.kind()) { case Symbol::DefinedKind: { - auto &D = cast(Sym); - SectionBase *IS = D.Section; + auto &d = cast(sym); + SectionBase *isec = d.section; // This is an absolute symbol. - if (!IS) - return D.Value; + if (!isec) + return d.value; - assert(IS != &InputSection::Discarded); - IS = IS->Repl; + assert(isec != &InputSection::discarded); + isec = isec->repl; - uint64_t Offset = D.Value; + uint64_t offset = d.value; // An object in an SHF_MERGE section might be referenced via a // section symbol (as a hack for reducing the number of local @@ -68,9 +68,9 @@ // To make this work, we incorporate the addend into the section // offset (and zero out the addend for later processing) so that // we find the right object in the section. - if (D.isSection()) { - Offset += Addend; - Addend = 0; + if (d.isSection()) { + offset += addend; + addend = 0; } // In the typical case, this is actually very simple and boils @@ -83,7 +83,7 @@ // If you understand the data structures involved with this next // line (and how they get built), then you have a pretty good // understanding of the linker. - uint64_t VA = IS->getVA(Offset); + uint64_t va = isec->getVA(offset); // MIPS relocatable files can mix regular and microMIPS code. // Linker needs to distinguish such code. To do so microMIPS @@ -94,29 +94,29 @@ // a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry` // field etc) do the same trick as compiler uses to mark microMIPS // for CPU - set the less-significant bit. - if (Config->EMachine == EM_MIPS && isMicroMips() && - ((Sym.StOther & STO_MIPS_MICROMIPS) || Sym.NeedsPltAddr)) - VA |= 1; + if (config->emachine == EM_MIPS && isMicroMips() && + ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsPltAddr)) + va |= 1; - if (D.isTls() && !Config->Relocatable) { + if (d.isTls() && !config->relocatable) { // Use the address of the TLS segment's first section rather than the // segment's address, because segment addresses aren't initialized until // after sections are finalized. (e.g. Measuring the size of .rela.dyn // for Android relocation packing requires knowing TLS symbol addresses // during section finalization.) - if (!Out::TlsPhdr || !Out::TlsPhdr->FirstSec) - fatal(toString(D.File) + + if (!Out::tlsPhdr || !Out::tlsPhdr->firstSec) + fatal(toString(d.file) + " has an STT_TLS symbol but doesn't have an SHF_TLS section"); - return VA - Out::TlsPhdr->FirstSec->Addr; + return va - Out::tlsPhdr->firstSec->addr; } - return VA; + return va; } case Symbol::SharedKind: case Symbol::UndefinedKind: return 0; case Symbol::LazyArchiveKind: case Symbol::LazyObjectKind: - assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer"); + assert(sym.isUsedInRegularObj && "lazy symbol reached writer"); return 0; case Symbol::CommonKind: llvm_unreachable("common symbol reached writer"); @@ -126,64 +126,64 @@ llvm_unreachable("invalid symbol kind"); } -uint64_t Symbol::getVA(int64_t Addend) const { - uint64_t OutVA = getSymVA(*this, Addend); - return OutVA + Addend; +uint64_t Symbol::getVA(int64_t addend) const { + uint64_t outVA = getSymVA(*this, addend); + return outVA + addend; } uint64_t Symbol::getGotVA() const { - if (GotInIgot) - return In.IgotPlt->getVA() + getGotPltOffset(); - return In.Got->getVA() + getGotOffset(); + if (gotInIgot) + return in.igotPlt->getVA() + getGotPltOffset(); + return in.got->getVA() + getGotOffset(); } -uint64_t Symbol::getGotOffset() const { return GotIndex * Config->Wordsize; } +uint64_t Symbol::getGotOffset() const { return gotIndex * config->wordsize; } uint64_t Symbol::getGotPltVA() const { - if (IsInIplt) - return In.IgotPlt->getVA() + getGotPltOffset(); - return In.GotPlt->getVA() + getGotPltOffset(); + if (isInIplt) + return in.igotPlt->getVA() + getGotPltOffset(); + return in.gotPlt->getVA() + getGotPltOffset(); } uint64_t Symbol::getGotPltOffset() const { - if (IsInIplt) - return PltIndex * Config->Wordsize; - return (PltIndex + Target->GotPltHeaderEntriesNum) * Config->Wordsize; + if (isInIplt) + return pltIndex * config->wordsize; + return (pltIndex + target->gotPltHeaderEntriesNum) * config->wordsize; } uint64_t Symbol::getPPC64LongBranchOffset() const { - assert(PPC64BranchltIndex != 0xffff); - return PPC64BranchltIndex * Config->Wordsize; + assert(ppc64BranchltIndex != 0xffff); + return ppc64BranchltIndex * config->wordsize; } uint64_t Symbol::getPltVA() const { - PltSection *Plt = IsInIplt ? In.Iplt : In.Plt; - uint64_t OutVA = - Plt->getVA() + Plt->HeaderSize + PltIndex * Target->PltEntrySize; + PltSection *plt = isInIplt ? in.iplt : in.plt; + uint64_t outVA = + plt->getVA() + plt->headerSize + pltIndex * target->pltEntrySize; // While linking microMIPS code PLT code are always microMIPS // code. Set the less-significant bit to track that fact. // See detailed comment in the `getSymVA` function. - if (Config->EMachine == EM_MIPS && isMicroMips()) - OutVA |= 1; - return OutVA; + if (config->emachine == EM_MIPS && isMicroMips()) + outVA |= 1; + return outVA; } uint64_t Symbol::getPPC64LongBranchTableVA() const { - assert(PPC64BranchltIndex != 0xffff); - return In.PPC64LongBranchTarget->getVA() + - PPC64BranchltIndex * Config->Wordsize; + assert(ppc64BranchltIndex != 0xffff); + return in.ppc64LongBranchTarget->getVA() + + ppc64BranchltIndex * config->wordsize; } uint64_t Symbol::getSize() const { - if (const auto *DR = dyn_cast(this)) - return DR->Size; - return cast(this)->Size; + if (const auto *dr = dyn_cast(this)) + return dr->size; + return cast(this)->size; } OutputSection *Symbol::getOutputSection() const { - if (auto *S = dyn_cast(this)) { - if (auto *Sec = S->Section) - return Sec->Repl->getOutputSection(); + if (auto *s = dyn_cast(this)) { + if (auto *sec = s->section) + return sec->repl->getOutputSection(); return nullptr; } return nullptr; @@ -192,16 +192,16 @@ // If a symbol name contains '@', the characters after that is // a symbol version name. This function parses that. void Symbol::parseSymbolVersion() { - StringRef S = getName(); - size_t Pos = S.find('@'); - if (Pos == 0 || Pos == StringRef::npos) + StringRef s = getName(); + size_t pos = s.find('@'); + if (pos == 0 || pos == StringRef::npos) return; - StringRef Verstr = S.substr(Pos + 1); - if (Verstr.empty()) + StringRef verstr = s.substr(pos + 1); + if (verstr.empty()) return; // Truncate the symbol name so that it doesn't include the version string. - NameSize = Pos; + nameSize = pos; // If this is not in this DSO, it is not a definition. if (!isDefined()) @@ -209,18 +209,18 @@ // '@@' in a symbol name means the default version. // It is usually the most recent one. - bool IsDefault = (Verstr[0] == '@'); - if (IsDefault) - Verstr = Verstr.substr(1); + bool isDefault = (verstr[0] == '@'); + if (isDefault) + verstr = verstr.substr(1); - for (VersionDefinition &Ver : Config->VersionDefinitions) { - if (Ver.Name != Verstr) + for (VersionDefinition &ver : config->versionDefinitions) { + if (ver.name != verstr) continue; - if (IsDefault) - VersionId = Ver.Id; + if (isDefault) + versionId = ver.id; else - VersionId = Ver.Id | VERSYM_HIDDEN; + versionId = ver.id | VERSYM_HIDDEN; return; } @@ -230,19 +230,19 @@ // so we do not report error in this case. We also do not error // if the symbol has a local version as it won't be in the dynamic // symbol table. - if (Config->Shared && VersionId != VER_NDX_LOCAL) - error(toString(File) + ": symbol " + S + " has undefined version " + - Verstr); + if (config->shared && versionId != VER_NDX_LOCAL) + error(toString(file) + ": symbol " + s + " has undefined version " + + verstr); } void Symbol::fetch() const { - if (auto *Sym = dyn_cast(this)) { - cast(Sym->File)->fetch(Sym->Sym); + if (auto *sym = dyn_cast(this)) { + cast(sym->file)->fetch(sym->sym); return; } - if (auto *Sym = dyn_cast(this)) { - dyn_cast(Sym->File)->fetch(); + if (auto *sym = dyn_cast(this)) { + dyn_cast(sym->file)->fetch(); return; } @@ -250,59 +250,59 @@ } MemoryBufferRef LazyArchive::getMemberBuffer() { - Archive::Child C = CHECK( - Sym.getMember(), "could not get the member for symbol " + Sym.getName()); + Archive::Child c = CHECK( + sym.getMember(), "could not get the member for symbol " + sym.getName()); - return CHECK(C.getMemoryBufferRef(), + return CHECK(c.getMemoryBufferRef(), "could not get the buffer for the member defining symbol " + - Sym.getName()); + sym.getName()); } uint8_t Symbol::computeBinding() const { - if (Config->Relocatable) - return Binding; - if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) + if (config->relocatable) + return binding; + if (visibility != STV_DEFAULT && visibility != STV_PROTECTED) return STB_LOCAL; - if (VersionId == VER_NDX_LOCAL && isDefined() && !IsPreemptible) + if (versionId == VER_NDX_LOCAL && isDefined() && !isPreemptible) return STB_LOCAL; - if (!Config->GnuUnique && Binding == STB_GNU_UNIQUE) + if (!config->gnuUnique && binding == STB_GNU_UNIQUE) return STB_GLOBAL; - return Binding; + return binding; } bool Symbol::includeInDynsym() const { - if (!Config->HasDynSymTab) + if (!config->hasDynSymTab) return false; if (computeBinding() == STB_LOCAL) return false; // If a PIE binary was not linked against any shared libraries, then we can // safely drop weak undef symbols from .dynsym. - if (isUndefWeak() && Config->Pie && SharedFiles.empty()) + if (isUndefWeak() && config->pie && sharedFiles.empty()) return false; - return isUndefined() || isShared() || ExportDynamic; + return isUndefined() || isShared() || exportDynamic; } // Print out a log message for --trace-symbol. -void elf::printTraceSymbol(const Symbol *Sym) { - std::string S; - if (Sym->isUndefined()) - S = ": reference to "; - else if (Sym->isLazy()) - S = ": lazy definition of "; - else if (Sym->isShared()) - S = ": shared definition of "; - else if (Sym->isCommon()) - S = ": common definition of "; +void elf::printTraceSymbol(const Symbol *sym) { + std::string s; + if (sym->isUndefined()) + s = ": reference to "; + else if (sym->isLazy()) + s = ": lazy definition of "; + else if (sym->isShared()) + s = ": shared definition of "; + else if (sym->isCommon()) + s = ": common definition of "; else - S = ": definition of "; + s = ": definition of "; - message(toString(Sym->File) + S + Sym->getName()); + message(toString(sym->file) + s + sym->getName()); } -void elf::maybeWarnUnorderableSymbol(const Symbol *Sym) { - if (!Config->WarnSymbolOrdering) +void elf::maybeWarnUnorderableSymbol(const Symbol *sym) { + if (!config->warnSymbolOrdering) return; // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning @@ -310,41 +310,41 @@ // // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols, // but we don't have to be compatible here. - if (Sym->isUndefined() && - Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) + if (sym->isUndefined() && + config->unresolvedSymbols == UnresolvedPolicy::Ignore) return; - const InputFile *File = Sym->File; - auto *D = dyn_cast(Sym); + const InputFile *file = sym->file; + auto *d = dyn_cast(sym); - auto Report = [&](StringRef S) { warn(toString(File) + S + Sym->getName()); }; + auto report = [&](StringRef s) { warn(toString(file) + s + sym->getName()); }; - if (Sym->isUndefined()) - Report(": unable to order undefined symbol: "); - else if (Sym->isShared()) - Report(": unable to order shared symbol: "); - else if (D && !D->Section) - Report(": unable to order absolute symbol: "); - else if (D && isa(D->Section)) - Report(": unable to order synthetic symbol: "); - else if (D && !D->Section->Repl->isLive()) - Report(": unable to order discarded symbol: "); + if (sym->isUndefined()) + report(": unable to order undefined symbol: "); + else if (sym->isShared()) + report(": unable to order shared symbol: "); + else if (d && !d->section) + report(": unable to order absolute symbol: "); + else if (d && isa(d->section)) + report(": unable to order synthetic symbol: "); + else if (d && !d->section->repl->isLive()) + report(": unable to order discarded symbol: "); } // Returns a symbol for an error message. -std::string lld::toString(const Symbol &B) { - if (Config->Demangle) - if (Optional S = demangleItanium(B.getName())) - return *S; - return B.getName(); +std::string lld::toString(const Symbol &b) { + if (config->demangle) + if (Optional s = demangleItanium(b.getName())) + return *s; + return b.getName(); } -static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { - if (VA == STV_DEFAULT) - return VB; - if (VB == STV_DEFAULT) - return VA; - return std::min(VA, VB); +static uint8_t getMinVisibility(uint8_t va, uint8_t vb) { + if (va == STV_DEFAULT) + return vb; + if (vb == STV_DEFAULT) + return va; + return std::min(va, vb); } // Merge symbol properties. @@ -352,70 +352,70 @@ // When we have many symbols of the same name, we choose one of them, // and that's the result of symbol resolution. However, symbols that // were not chosen still affect some symbol properties. -void Symbol::mergeProperties(const Symbol &Other) { - if (Other.ExportDynamic) - ExportDynamic = true; - if (Other.IsUsedInRegularObj) - IsUsedInRegularObj = true; +void Symbol::mergeProperties(const Symbol &other) { + if (other.exportDynamic) + exportDynamic = true; + if (other.isUsedInRegularObj) + isUsedInRegularObj = true; // DSO symbols do not affect visibility in the output. - if (!Other.isShared()) - Visibility = getMinVisibility(Visibility, Other.Visibility); + if (!other.isShared()) + visibility = getMinVisibility(visibility, other.visibility); } -void Symbol::resolve(const Symbol &Other) { - mergeProperties(Other); +void Symbol::resolve(const Symbol &other) { + mergeProperties(other); if (isPlaceholder()) { - replace(Other); + replace(other); return; } - switch (Other.kind()) { + switch (other.kind()) { case Symbol::UndefinedKind: - resolveUndefined(cast(Other)); + resolveUndefined(cast(other)); break; case Symbol::CommonKind: - resolveCommon(cast(Other)); + resolveCommon(cast(other)); break; case Symbol::DefinedKind: - resolveDefined(cast(Other)); + resolveDefined(cast(other)); break; case Symbol::LazyArchiveKind: - resolveLazy(cast(Other)); + resolveLazy(cast(other)); break; case Symbol::LazyObjectKind: - resolveLazy(cast(Other)); + resolveLazy(cast(other)); break; case Symbol::SharedKind: - resolveShared(cast(Other)); + resolveShared(cast(other)); break; case Symbol::PlaceholderKind: llvm_unreachable("bad symbol kind"); } } -void Symbol::resolveUndefined(const Undefined &Other) { +void Symbol::resolveUndefined(const Undefined &other) { // An undefined symbol with non default visibility must be satisfied // in the same DSO. // // If this is a non-weak defined symbol in a discarded section, override the // existing undefined symbol for better error message later. - if ((isShared() && Other.Visibility != STV_DEFAULT) || - (isUndefined() && Other.Binding != STB_WEAK && Other.DiscardedSecIdx)) { - replace(Other); + if ((isShared() && other.visibility != STV_DEFAULT) || + (isUndefined() && other.binding != STB_WEAK && other.discardedSecIdx)) { + replace(other); return; } - if (Traced) - printTraceSymbol(&Other); + if (traced) + printTraceSymbol(&other); if (isLazy()) { // An undefined weak will not fetch archive members. See comment on Lazy in // Symbols.h for the details. - if (Other.Binding == STB_WEAK) { - Binding = STB_WEAK; - Type = Other.Type; + if (other.binding == STB_WEAK) { + binding = STB_WEAK; + type = other.type; return; } @@ -469,33 +469,33 @@ // A forms group 0. B form group 1. C and D (including their member object // files) form group 2. E forms group 3. I think that you can see how this // group assignment rule simulates the traditional linker's semantics. - bool Backref = Config->WarnBackrefs && Other.File && - File->GroupId < Other.File->GroupId; + bool backref = config->warnBackrefs && other.file && + file->groupId < other.file->groupId; fetch(); // We don't report backward references to weak symbols as they can be // overridden later. - if (Backref && !isWeak()) - warn("backward reference detected: " + Other.getName() + " in " + - toString(Other.File) + " refers to " + toString(File)); + if (backref && !isWeak()) + warn("backward reference detected: " + other.getName() + " in " + + toString(other.file) + " refers to " + toString(file)); return; } // Undefined symbols in a SharedFile do not change the binding. - if (dyn_cast_or_null(Other.File)) + if (dyn_cast_or_null(other.file)) return; if (isUndefined()) { // The binding may "upgrade" from weak to non-weak. - if (Other.Binding != STB_WEAK) - Binding = Other.Binding; - } else if (auto *S = dyn_cast(this)) { + if (other.binding != STB_WEAK) + binding = other.binding; + } else if (auto *s = dyn_cast(this)) { // The binding of a SharedSymbol will be weak if there is at least one // reference and all are weak. The binding has one opportunity to change to // weak: if the first reference is weak. - if (Other.Binding != STB_WEAK || !S->Referenced) - Binding = Other.Binding; - S->Referenced = true; + if (other.binding != STB_WEAK || !s->referenced) + binding = other.binding; + s->referenced = true; } } @@ -505,73 +505,73 @@ // FIXME: If users can transition to using // .symver foo,foo@@@VER // we can delete this hack. -static int compareVersion(StringRef A, StringRef B) { - bool X = A.contains("@@"); - bool Y = B.contains("@@"); - if (!X && Y) +static int compareVersion(StringRef a, StringRef b) { + bool x = a.contains("@@"); + bool y = b.contains("@@"); + if (!x && y) return 1; - if (X && !Y) + if (x && !y) return -1; return 0; } // Compare two symbols. Return 1 if the new symbol should win, -1 if // the new symbol should lose, or 0 if there is a conflict. -int Symbol::compare(const Symbol *Other) const { - assert(Other->isDefined() || Other->isCommon()); +int Symbol::compare(const Symbol *other) const { + assert(other->isDefined() || other->isCommon()); if (!isDefined() && !isCommon()) return 1; - if (int Cmp = compareVersion(getName(), Other->getName())) - return Cmp; + if (int cmp = compareVersion(getName(), other->getName())) + return cmp; - if (Other->isWeak()) + if (other->isWeak()) return -1; if (isWeak()) return 1; - if (isCommon() && Other->isCommon()) { - if (Config->WarnCommon) + if (isCommon() && other->isCommon()) { + if (config->warnCommon) warn("multiple common of " + getName()); return 0; } if (isCommon()) { - if (Config->WarnCommon) + if (config->warnCommon) warn("common " + getName() + " is overridden"); return 1; } - if (Other->isCommon()) { - if (Config->WarnCommon) + if (other->isCommon()) { + if (config->warnCommon) warn("common " + getName() + " is overridden"); return -1; } - auto *OldSym = cast(this); - auto *NewSym = cast(Other); + auto *oldSym = cast(this); + auto *newSym = cast(other); - if (Other->File && isa(Other->File)) + if (other->file && isa(other->file)) return 0; - if (!OldSym->Section && !NewSym->Section && OldSym->Value == NewSym->Value && - NewSym->Binding == STB_GLOBAL) + if (!oldSym->section && !newSym->section && oldSym->value == newSym->value && + newSym->binding == STB_GLOBAL) return -1; return 0; } -static void reportDuplicate(Symbol *Sym, InputFile *NewFile, - InputSectionBase *ErrSec, uint64_t ErrOffset) { - if (Config->AllowMultipleDefinition) +static void reportDuplicate(Symbol *sym, InputFile *newFile, + InputSectionBase *errSec, uint64_t errOffset) { + if (config->allowMultipleDefinition) return; - Defined *D = cast(Sym); - if (!D->Section || !ErrSec) { - error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + - toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); + Defined *d = cast(sym); + if (!d->section || !errSec) { + error("duplicate symbol: " + toString(*sym) + "\n>>> defined in " + + toString(sym->file) + "\n>>> defined in " + toString(newFile)); return; } @@ -582,75 +582,75 @@ // >>> bar.o (/home/alice/src/bar.o) // >>> defined at baz.c:563 // >>> baz.o in archive libbaz.a - auto *Sec1 = cast(D->Section); - std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); - std::string Obj1 = Sec1->getObjMsg(D->Value); - std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); - std::string Obj2 = ErrSec->getObjMsg(ErrOffset); + auto *sec1 = cast(d->section); + std::string src1 = sec1->getSrcMsg(*sym, d->value); + std::string obj1 = sec1->getObjMsg(d->value); + std::string src2 = errSec->getSrcMsg(*sym, errOffset); + std::string obj2 = errSec->getObjMsg(errOffset); - std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; - if (!Src1.empty()) - Msg += Src1 + "\n>>> "; - Msg += Obj1 + "\n>>> defined at "; - if (!Src2.empty()) - Msg += Src2 + "\n>>> "; - Msg += Obj2; - error(Msg); + std::string msg = "duplicate symbol: " + toString(*sym) + "\n>>> defined at "; + if (!src1.empty()) + msg += src1 + "\n>>> "; + msg += obj1 + "\n>>> defined at "; + if (!src2.empty()) + msg += src2 + "\n>>> "; + msg += obj2; + error(msg); } -void Symbol::resolveCommon(const CommonSymbol &Other) { - int Cmp = compare(&Other); - if (Cmp < 0) +void Symbol::resolveCommon(const CommonSymbol &other) { + int cmp = compare(&other); + if (cmp < 0) return; - if (Cmp > 0) { - replace(Other); + if (cmp > 0) { + replace(other); return; } - CommonSymbol *OldSym = cast(this); + CommonSymbol *oldSym = cast(this); - OldSym->Alignment = std::max(OldSym->Alignment, Other.Alignment); - if (OldSym->Size < Other.Size) { - OldSym->File = Other.File; - OldSym->Size = Other.Size; + oldSym->alignment = std::max(oldSym->alignment, other.alignment); + if (oldSym->size < other.size) { + oldSym->file = other.file; + oldSym->size = other.size; } } -void Symbol::resolveDefined(const Defined &Other) { - int Cmp = compare(&Other); - if (Cmp > 0) - replace(Other); - else if (Cmp == 0) - reportDuplicate(this, Other.File, - dyn_cast_or_null(Other.Section), - Other.Value); +void Symbol::resolveDefined(const Defined &other) { + int cmp = compare(&other); + if (cmp > 0) + replace(other); + else if (cmp == 0) + reportDuplicate(this, other.file, + dyn_cast_or_null(other.section), + other.value); } -template void Symbol::resolveLazy(const LazyT &Other) { +template void Symbol::resolveLazy(const LazyT &other) { if (!isUndefined()) return; // An undefined weak will not fetch archive members. See comment on Lazy in // Symbols.h for the details. if (isWeak()) { - uint8_t Ty = Type; - replace(Other); - Type = Ty; - Binding = STB_WEAK; + uint8_t ty = type; + replace(other); + type = ty; + binding = STB_WEAK; return; } - Other.fetch(); + other.fetch(); } -void Symbol::resolveShared(const SharedSymbol &Other) { - if (Visibility == STV_DEFAULT && (isUndefined() || isLazy())) { +void Symbol::resolveShared(const SharedSymbol &other) { + if (visibility == STV_DEFAULT && (isUndefined() || isLazy())) { // An undefined symbol with non default visibility must be satisfied // in the same DSO. - uint8_t Bind = Binding; - replace(Other); - Binding = Bind; - cast(this)->Referenced = true; + uint8_t bind = binding; + replace(other); + binding = bind; + cast(this)->referenced = true; } } Index: lld/trunk/ELF/SyntheticSections.h =================================================================== --- lld/trunk/ELF/SyntheticSections.h +++ lld/trunk/ELF/SyntheticSections.h @@ -37,15 +37,15 @@ class SyntheticSection : public InputSection { public: - SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment, - StringRef Name) - : InputSection(nullptr, Flags, Type, Alignment, {}, Name, + SyntheticSection(uint64_t flags, uint32_t type, uint32_t alignment, + StringRef name) + : InputSection(nullptr, flags, type, alignment, {}, name, InputSectionBase::Synthetic) { markLive(); } virtual ~SyntheticSection() = default; - virtual void writeTo(uint8_t *Buf) = 0; + virtual void writeTo(uint8_t *buf) = 0; virtual size_t getSize() const = 0; virtual void finalizeContents() {} // If the section has the SHF_ALLOC flag and the size may be changed if @@ -53,91 +53,91 @@ virtual bool updateAllocSize() { return false; } virtual bool isNeeded() const { return true; } - static bool classof(const SectionBase *D) { - return D->kind() == InputSectionBase::Synthetic; + static bool classof(const SectionBase *d) { + return d->kind() == InputSectionBase::Synthetic; } }; struct CieRecord { - EhSectionPiece *Cie = nullptr; - std::vector Fdes; + EhSectionPiece *cie = nullptr; + std::vector fdes; }; // Section for .eh_frame. class EhFrameSection final : public SyntheticSection { public: EhFrameSection(); - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; void finalizeContents() override; - bool isNeeded() const override { return !Sections.empty(); } - size_t getSize() const override { return Size; } + bool isNeeded() const override { return !sections.empty(); } + size_t getSize() const override { return size; } - static bool classof(const SectionBase *D) { - return SyntheticSection::classof(D) && D->Name == ".eh_frame"; + static bool classof(const SectionBase *d) { + return SyntheticSection::classof(d) && d->name == ".eh_frame"; } - template void addSection(InputSectionBase *S); + template void addSection(InputSectionBase *s); - std::vector Sections; - size_t NumFdes = 0; + std::vector sections; + size_t numFdes = 0; struct FdeData { - uint32_t PcRel; - uint32_t FdeVARel; + uint32_t pcRel; + uint32_t fdeVARel; }; std::vector getFdeData() const; - ArrayRef getCieRecords() const { return CieRecords; } + ArrayRef getCieRecords() const { return cieRecords; } private: // This is used only when parsing EhInputSection. We keep it here to avoid // allocating one for each EhInputSection. - llvm::DenseMap OffsetToCie; + llvm::DenseMap offsetToCie; - uint64_t Size = 0; + uint64_t size = 0; template - void addSectionAux(EhInputSection *S, llvm::ArrayRef Rels); + void addSectionAux(EhInputSection *s, llvm::ArrayRef rels); template - CieRecord *addCie(EhSectionPiece &Piece, ArrayRef Rels); + CieRecord *addCie(EhSectionPiece &piece, ArrayRef rels); template - bool isFdeLive(EhSectionPiece &Piece, ArrayRef Rels); + bool isFdeLive(EhSectionPiece &piece, ArrayRef rels); - uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc) const; + uint64_t getFdePc(uint8_t *buf, size_t off, uint8_t enc) const; - std::vector CieRecords; + std::vector cieRecords; // CIE records are uniquified by their contents and personality functions. - llvm::DenseMap, Symbol *>, CieRecord *> CieMap; + llvm::DenseMap, Symbol *>, CieRecord *> cieMap; }; class GotSection : public SyntheticSection { public: GotSection(); - size_t getSize() const override { return Size; } + size_t getSize() const override { return size; } void finalizeContents() override; bool isNeeded() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; - void addEntry(Symbol &Sym); - bool addDynTlsEntry(Symbol &Sym); + void addEntry(Symbol &sym); + bool addDynTlsEntry(Symbol &sym); bool addTlsIndex(); - uint64_t getGlobalDynAddr(const Symbol &B) const; - uint64_t getGlobalDynOffset(const Symbol &B) const; + uint64_t getGlobalDynAddr(const Symbol &b) const; + uint64_t getGlobalDynOffset(const Symbol &b) const; - uint64_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; } - uint32_t getTlsIndexOff() const { return TlsIndexOff; } + uint64_t getTlsIndexVA() { return this->getVA() + tlsIndexOff; } + uint32_t getTlsIndexOff() const { return tlsIndexOff; } // Flag to force GOT to be in output if we have relocations // that relies on its address. - bool HasGotOffRel = false; + bool hasGotOffRel = false; protected: - size_t NumEntries = 0; - uint32_t TlsIndexOff = -1; - uint64_t Size = 0; + size_t numEntries = 0; + uint32_t tlsIndexOff = -1; + uint64_t size = 0; }; // .note.GNU-stack section. @@ -145,31 +145,31 @@ public: GnuStackSection() : SyntheticSection(0, llvm::ELF::SHT_PROGBITS, 1, ".note.GNU-stack") {} - void writeTo(uint8_t *Buf) override {} + void writeTo(uint8_t *buf) override {} size_t getSize() const override { return 0; } }; class GnuPropertySection : public SyntheticSection { public: GnuPropertySection(); - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; size_t getSize() const override; }; // .note.gnu.build-id section. class BuildIdSection : public SyntheticSection { // First 16 bytes are a header. - static const unsigned HeaderSize = 16; + static const unsigned headerSize = 16; public: - const size_t HashSize; + const size_t hashSize; BuildIdSection(); - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return HeaderSize + HashSize; } - void writeBuildId(llvm::ArrayRef Buf); + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return headerSize + hashSize; } + void writeBuildId(llvm::ArrayRef buf); private: - uint8_t *HashBuf; + uint8_t *hashBuf; }; // BssSection is used to reserve space for copy relocations and common symbols. @@ -178,22 +178,22 @@ // respectively. class BssSection final : public SyntheticSection { public: - BssSection(StringRef Name, uint64_t Size, uint32_t Alignment); + BssSection(StringRef name, uint64_t size, uint32_t alignment); void writeTo(uint8_t *) override { llvm_unreachable("unexpected writeTo() call for SHT_NOBITS section"); } - bool isNeeded() const override { return Size != 0; } - size_t getSize() const override { return Size; } + bool isNeeded() const override { return size != 0; } + size_t getSize() const override { return size; } - static bool classof(const SectionBase *S) { return S->Bss; } - uint64_t Size; + static bool classof(const SectionBase *s) { return s->bss; } + uint64_t size; }; class MipsGotSection final : public SyntheticSection { public: MipsGotSection(); - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } bool updateAllocSize() override; void finalizeContents() override; bool isNeeded() const override; @@ -202,16 +202,16 @@ // primary and optional multiple secondary GOTs. void build(); - void addEntry(InputFile &File, Symbol &Sym, int64_t Addend, RelExpr Expr); - void addDynTlsEntry(InputFile &File, Symbol &Sym); - void addTlsIndex(InputFile &File); - - uint64_t getPageEntryOffset(const InputFile *F, const Symbol &S, - int64_t Addend) const; - uint64_t getSymEntryOffset(const InputFile *F, const Symbol &S, - int64_t Addend) const; - uint64_t getGlobalDynOffset(const InputFile *F, const Symbol &S) const; - uint64_t getTlsIndexOffset(const InputFile *F) const; + void addEntry(InputFile &file, Symbol &sym, int64_t addend, RelExpr expr); + void addDynTlsEntry(InputFile &file, Symbol &sym); + void addTlsIndex(InputFile &file); + + uint64_t getPageEntryOffset(const InputFile *f, const Symbol &s, + int64_t addend) const; + uint64_t getSymEntryOffset(const InputFile *f, const Symbol &s, + int64_t addend) const; + uint64_t getGlobalDynOffset(const InputFile *f, const Symbol &s) const; + uint64_t getTlsIndexOffset(const InputFile *f) const; // Returns the symbol which corresponds to the first entry of the global part // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic @@ -224,7 +224,7 @@ unsigned getLocalEntriesNum() const; // Return _gp value for primary GOT (nullptr) or particular input file. - uint64_t getGp(const InputFile *F = nullptr) const; + uint64_t getGp(const InputFile *f = nullptr) const; private: // MIPS GOT consists of three parts: local, global and tls. Each part @@ -314,35 +314,35 @@ // https://dmz-portal.mips.com/wiki/MIPS_Multi_GOT // Number of "Header" entries. - static const unsigned HeaderEntriesNum = 2; + static const unsigned headerEntriesNum = 2; - uint64_t Size = 0; + uint64_t size = 0; // Symbol and addend. using GotEntry = std::pair; struct FileGot { - InputFile *File = nullptr; - size_t StartIndex = 0; + InputFile *file = nullptr; + size_t startIndex = 0; struct PageBlock { - size_t FirstIndex; - size_t Count; - PageBlock() : FirstIndex(0), Count(0) {} + size_t firstIndex; + size_t count; + PageBlock() : firstIndex(0), count(0) {} }; // Map output sections referenced by MIPS GOT relocations // to the description (index/count) "page" entries allocated // for this section. - llvm::SmallMapVector PagesMap; + llvm::SmallMapVector pagesMap; // Maps from Symbol+Addend pair or just Symbol to the GOT entry index. - llvm::MapVector Local16; - llvm::MapVector Local32; - llvm::MapVector Global; - llvm::MapVector Relocs; - llvm::MapVector Tls; + llvm::MapVector local16; + llvm::MapVector local32; + llvm::MapVector global; + llvm::MapVector relocs; + llvm::MapVector tls; // Set of symbols referenced by dynamic TLS relocations. - llvm::MapVector DynTlsSymbols; + llvm::MapVector dynTlsSymbols; // Total number of all entries. size_t getEntriesNum() const; @@ -355,31 +355,31 @@ // Container of GOT created for each input file. // After building a final series of GOTs this container // holds primary and secondary GOT's. - std::vector Gots; + std::vector gots; // Return (and create if necessary) `FileGot`. - FileGot &getGot(InputFile &F); + FileGot &getGot(InputFile &f); // Try to merge two GOTs. In case of success the `Dst` contains // result of merging and the function returns true. In case of // ovwerflow the `Dst` is unchanged and the function returns false. - bool tryMergeGots(FileGot & Dst, FileGot & Src, bool IsPrimary); + bool tryMergeGots(FileGot & dst, FileGot & src, bool isPrimary); }; class GotPltSection final : public SyntheticSection { public: GotPltSection(); - void addEntry(Symbol &Sym); + void addEntry(Symbol &sym); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; bool isNeeded() const override; // Flag to force GotPlt to be in output if we have relocations // that relies on its address. - bool HasGotPltOffRel = false; + bool hasGotPltOffRel = false; private: - std::vector Entries; + std::vector entries; }; // The IgotPltSection is a Got associated with the PltSection for GNU Ifunc @@ -389,67 +389,67 @@ class IgotPltSection final : public SyntheticSection { public: IgotPltSection(); - void addEntry(Symbol &Sym); + void addEntry(Symbol &sym); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; - bool isNeeded() const override { return !Entries.empty(); } + void writeTo(uint8_t *buf) override; + bool isNeeded() const override { return !entries.empty(); } private: - std::vector Entries; + std::vector entries; }; class StringTableSection final : public SyntheticSection { public: - StringTableSection(StringRef Name, bool Dynamic); - unsigned addString(StringRef S, bool HashIt = true); - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } - bool isDynamic() const { return Dynamic; } + StringTableSection(StringRef name, bool dynamic); + unsigned addString(StringRef s, bool hashIt = true); + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } + bool isDynamic() const { return dynamic; } private: - const bool Dynamic; + const bool dynamic; - uint64_t Size = 0; + uint64_t size = 0; - llvm::DenseMap StringMap; - std::vector Strings; + llvm::DenseMap stringMap; + std::vector strings; }; class DynamicReloc { public: - DynamicReloc(RelType Type, const InputSectionBase *InputSec, - uint64_t OffsetInSec, bool UseSymVA, Symbol *Sym, int64_t Addend) - : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec), - UseSymVA(UseSymVA), Addend(Addend), OutputSec(nullptr) {} + DynamicReloc(RelType type, const InputSectionBase *inputSec, + uint64_t offsetInSec, bool useSymVA, Symbol *sym, int64_t addend) + : type(type), sym(sym), inputSec(inputSec), offsetInSec(offsetInSec), + useSymVA(useSymVA), addend(addend), outputSec(nullptr) {} // This constructor records dynamic relocation settings used by MIPS // multi-GOT implementation. It's to relocate addresses of 64kb pages // lie inside the output section. - DynamicReloc(RelType Type, const InputSectionBase *InputSec, - uint64_t OffsetInSec, const OutputSection *OutputSec, - int64_t Addend) - : Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec), - UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {} + DynamicReloc(RelType type, const InputSectionBase *inputSec, + uint64_t offsetInSec, const OutputSection *outputSec, + int64_t addend) + : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), + useSymVA(false), addend(addend), outputSec(outputSec) {} uint64_t getOffset() const; - uint32_t getSymIndex(SymbolTableBaseSection *SymTab) const; + uint32_t getSymIndex(SymbolTableBaseSection *symTab) const; // Computes the addend of the dynamic relocation. Note that this is not the // same as the Addend member variable as it also includes the symbol address // if UseSymVA is true. int64_t computeAddend() const; - RelType Type; + RelType type; - Symbol *Sym; - const InputSectionBase *InputSec = nullptr; - uint64_t OffsetInSec; + Symbol *sym; + const InputSectionBase *inputSec = nullptr; + uint64_t offsetInSec; // If this member is true, the dynamic relocation will not be against the // symbol but will instead be a relative relocation that simply adds the // load address. This means we need to write the symbol virtual address // plus the original addend as the final relocation addend. - bool UseSymVA; - int64_t Addend; - const OutputSection *OutputSec; + bool useSymVA; + int64_t addend; + const OutputSection *outputSec; }; template class DynamicSection final : public SyntheticSection { @@ -461,47 +461,47 @@ using Elf_Sym = typename ELFT::Sym; // finalizeContents() fills this vector with the section contents. - std::vector>> Entries; + std::vector>> entries; public: DynamicSection(); void finalizeContents() override; - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } private: - void add(int32_t Tag, std::function Fn); - void addInt(int32_t Tag, uint64_t Val); - void addInSec(int32_t Tag, InputSection *Sec); - void addInSecRelative(int32_t Tag, InputSection *Sec); - void addOutSec(int32_t Tag, OutputSection *Sec); - void addSize(int32_t Tag, OutputSection *Sec); - void addSym(int32_t Tag, Symbol *Sym); + void add(int32_t tag, std::function fn); + void addInt(int32_t tag, uint64_t val); + void addInSec(int32_t tag, InputSection *sec); + void addInSecRelative(int32_t tag, InputSection *sec); + void addOutSec(int32_t tag, OutputSection *sec); + void addSize(int32_t tag, OutputSection *sec); + void addSym(int32_t tag, Symbol *sym); - uint64_t Size = 0; + uint64_t size = 0; }; class RelocationBaseSection : public SyntheticSection { public: - RelocationBaseSection(StringRef Name, uint32_t Type, int32_t DynamicTag, - int32_t SizeDynamicTag); - void addReloc(RelType DynType, InputSectionBase *IS, uint64_t OffsetInSec, - Symbol *Sym); + RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag, + int32_t sizeDynamicTag); + void addReloc(RelType dynType, InputSectionBase *isec, uint64_t offsetInSec, + Symbol *sym); // Add a dynamic relocation that might need an addend. This takes care of // writing the addend to the output section if needed. - void addReloc(RelType DynType, InputSectionBase *InputSec, - uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr, - RelType Type); - void addReloc(const DynamicReloc &Reloc); - bool isNeeded() const override { return !Relocs.empty(); } - size_t getSize() const override { return Relocs.size() * this->Entsize; } - size_t getRelativeRelocCount() const { return NumRelativeRelocs; } + void addReloc(RelType dynType, InputSectionBase *inputSec, + uint64_t offsetInSec, Symbol *sym, int64_t addend, RelExpr expr, + RelType type); + void addReloc(const DynamicReloc &reloc); + bool isNeeded() const override { return !relocs.empty(); } + size_t getSize() const override { return relocs.size() * this->entsize; } + size_t getRelativeRelocCount() const { return numRelativeRelocs; } void finalizeContents() override; - int32_t DynamicTag, SizeDynamicTag; - std::vector Relocs; + int32_t dynamicTag, sizeDynamicTag; + std::vector relocs; protected: - size_t NumRelativeRelocs = 0; + size_t numRelativeRelocs = 0; }; template @@ -510,11 +510,11 @@ using Elf_Rela = typename ELFT::Rela; public: - RelocationSection(StringRef Name, bool Sort); - void writeTo(uint8_t *Buf) override; + RelocationSection(StringRef name, bool sort); + void writeTo(uint8_t *buf) override; private: - bool Sort; + bool sort; }; template @@ -523,30 +523,30 @@ using Elf_Rela = typename ELFT::Rela; public: - AndroidPackedRelocationSection(StringRef Name); + AndroidPackedRelocationSection(StringRef name); bool updateAllocSize() override; - size_t getSize() const override { return RelocData.size(); } - void writeTo(uint8_t *Buf) override { - memcpy(Buf, RelocData.data(), RelocData.size()); + size_t getSize() const override { return relocData.size(); } + void writeTo(uint8_t *buf) override { + memcpy(buf, relocData.data(), relocData.size()); } private: - SmallVector RelocData; + SmallVector relocData; }; struct RelativeReloc { - uint64_t getOffset() const { return InputSec->getVA(OffsetInSec); } + uint64_t getOffset() const { return inputSec->getVA(offsetInSec); } - const InputSectionBase *InputSec; - uint64_t OffsetInSec; + const InputSectionBase *inputSec; + uint64_t offsetInSec; }; class RelrBaseSection : public SyntheticSection { public: RelrBaseSection(); - bool isNeeded() const override { return !Relocs.empty(); } - std::vector Relocs; + bool isNeeded() const override { return !relocs.empty(); } + std::vector relocs; }; // RelrSection is used to encode offsets for relative relocations. @@ -560,41 +560,41 @@ RelrSection(); bool updateAllocSize() override; - size_t getSize() const override { return RelrRelocs.size() * this->Entsize; } - void writeTo(uint8_t *Buf) override { - memcpy(Buf, RelrRelocs.data(), getSize()); + size_t getSize() const override { return relrRelocs.size() * this->entsize; } + void writeTo(uint8_t *buf) override { + memcpy(buf, relrRelocs.data(), getSize()); } private: - std::vector RelrRelocs; + std::vector relrRelocs; }; struct SymbolTableEntry { - Symbol *Sym; - size_t StrTabOffset; + Symbol *sym; + size_t strTabOffset; }; class SymbolTableBaseSection : public SyntheticSection { public: - SymbolTableBaseSection(StringTableSection &StrTabSec); + SymbolTableBaseSection(StringTableSection &strTabSec); void finalizeContents() override; - size_t getSize() const override { return getNumSymbols() * Entsize; } - void addSymbol(Symbol *Sym); - unsigned getNumSymbols() const { return Symbols.size() + 1; } - size_t getSymbolIndex(Symbol *Sym); - ArrayRef getSymbols() const { return Symbols; } + size_t getSize() const override { return getNumSymbols() * entsize; } + void addSymbol(Symbol *sym); + unsigned getNumSymbols() const { return symbols.size() + 1; } + size_t getSymbolIndex(Symbol *sym); + ArrayRef getSymbols() const { return symbols; } protected: void sortSymTabSymbols(); // A vector of symbols and their string table offsets. - std::vector Symbols; + std::vector symbols; - StringTableSection &StrTabSec; + StringTableSection &strTabSec; - llvm::once_flag OnceFlag; - llvm::DenseMap SymbolIndexMap; - llvm::DenseMap SectionIndexMap; + llvm::once_flag onceFlag; + llvm::DenseMap symbolIndexMap; + llvm::DenseMap sectionIndexMap; }; template @@ -602,15 +602,15 @@ using Elf_Sym = typename ELFT::Sym; public: - SymbolTableSection(StringTableSection &StrTabSec); - void writeTo(uint8_t *Buf) override; + SymbolTableSection(StringTableSection &strTabSec); + void writeTo(uint8_t *buf) override; }; class SymtabShndxSection final : public SyntheticSection { public: SymtabShndxSection(); - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; size_t getSize() const override; bool isNeeded() const override; void finalizeContents() override; @@ -622,42 +622,42 @@ public: GnuHashTableSection(); void finalizeContents() override; - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } // Adds symbols to the hash table. // Sorts the input to satisfy GNU hash section requirements. - void addSymbols(std::vector &Symbols); + void addSymbols(std::vector &symbols); private: // See the comment in writeBloomFilter. enum { Shift2 = 26 }; - void writeBloomFilter(uint8_t *Buf); - void writeHashTable(uint8_t *Buf); + void writeBloomFilter(uint8_t *buf); + void writeHashTable(uint8_t *buf); struct Entry { - Symbol *Sym; - size_t StrTabOffset; - uint32_t Hash; - uint32_t BucketIdx; + Symbol *sym; + size_t strTabOffset; + uint32_t hash; + uint32_t bucketIdx; }; - std::vector Symbols; - size_t MaskWords; - size_t NBuckets = 0; - size_t Size = 0; + std::vector symbols; + size_t maskWords; + size_t nBuckets = 0; + size_t size = 0; }; class HashTableSection final : public SyntheticSection { public: HashTableSection(); void finalizeContents() override; - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } private: - size_t Size = 0; + size_t size = 0; }; // The PltSection is used for both the Plt and Iplt. The former usually has a @@ -666,66 +666,66 @@ // Target->IRelativeRel. class PltSection : public SyntheticSection { public: - PltSection(bool IsIplt); - void writeTo(uint8_t *Buf) override; + PltSection(bool isIplt); + void writeTo(uint8_t *buf) override; size_t getSize() const override; - bool isNeeded() const override { return !Entries.empty(); } + bool isNeeded() const override { return !entries.empty(); } void addSymbols(); - template void addEntry(Symbol &Sym); + template void addEntry(Symbol &sym); - size_t HeaderSize; + size_t headerSize; private: - std::vector Entries; - bool IsIplt; + std::vector entries; + bool isIplt; }; class GdbIndexSection final : public SyntheticSection { public: struct AddressEntry { - InputSection *Section; - uint64_t LowAddress; - uint64_t HighAddress; - uint32_t CuIndex; + InputSection *section; + uint64_t lowAddress; + uint64_t highAddress; + uint32_t cuIndex; }; struct CuEntry { - uint64_t CuOffset; - uint64_t CuLength; + uint64_t cuOffset; + uint64_t cuLength; }; struct NameAttrEntry { - llvm::CachedHashStringRef Name; - uint32_t CuIndexAndAttrs; + llvm::CachedHashStringRef name; + uint32_t cuIndexAndAttrs; }; struct GdbChunk { - InputSection *Sec; - std::vector AddressAreas; - std::vector CompilationUnits; + InputSection *sec; + std::vector addressAreas; + std::vector compilationUnits; }; struct GdbSymbol { - llvm::CachedHashStringRef Name; - std::vector CuVector; - uint32_t NameOff; - uint32_t CuVectorOff; + llvm::CachedHashStringRef name; + std::vector cuVector; + uint32_t nameOff; + uint32_t cuVectorOff; }; GdbIndexSection(); template static GdbIndexSection *create(); - void writeTo(uint8_t *Buf) override; - size_t getSize() const override { return Size; } + void writeTo(uint8_t *buf) override; + size_t getSize() const override { return size; } bool isNeeded() const override; private: struct GdbIndexHeader { - llvm::support::ulittle32_t Version; - llvm::support::ulittle32_t CuListOff; - llvm::support::ulittle32_t CuTypesOff; - llvm::support::ulittle32_t AddressAreaOff; - llvm::support::ulittle32_t SymtabOff; - llvm::support::ulittle32_t ConstantPoolOff; + llvm::support::ulittle32_t version; + llvm::support::ulittle32_t cuListOff; + llvm::support::ulittle32_t cuTypesOff; + llvm::support::ulittle32_t addressAreaOff; + llvm::support::ulittle32_t symtabOff; + llvm::support::ulittle32_t constantPoolOff; }; void initOutputSize(); @@ -733,12 +733,12 @@ // Each chunk contains information gathered from debug sections of a // single object file. - std::vector Chunks; + std::vector chunks; // A symbol table for this .gdb_index section. - std::vector Symbols; + std::vector symbols; - size_t Size; + size_t size; }; // --eh-frame-hdr option tells linker to construct a header for all the @@ -754,7 +754,7 @@ public: EhFrameHeader(); void write(); - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; size_t getSize() const override; bool isNeeded() const override; }; @@ -772,15 +772,15 @@ VersionDefinitionSection(); void finalizeContents() override; size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; private: enum { EntrySize = 28 }; - void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); + void writeOne(uint8_t *buf, uint32_t index, StringRef name, size_t nameOff); StringRef getFileDefName(); - unsigned FileDefNameOff; - std::vector VerDefNameOffs; + unsigned fileDefNameOff; + std::vector verDefNameOffs; }; // The .gnu.version section specifies the required version of each symbol in the @@ -794,7 +794,7 @@ VersionTableSection(); void finalizeContents() override; size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; bool isNeeded() const override; }; @@ -809,22 +809,22 @@ using Elf_Vernaux = typename ELFT::Vernaux; struct Vernaux { - uint64_t Hash; - uint32_t VerneedIndex; - uint64_t NameStrTab; + uint64_t hash; + uint32_t verneedIndex; + uint64_t nameStrTab; }; struct Verneed { - uint64_t NameStrTab; - std::vector Vernauxs; + uint64_t nameStrTab; + std::vector vernauxs; }; - std::vector Verneeds; + std::vector verneeds; public: VersionNeedSection(); void finalizeContents() override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; size_t getSize() const override; bool isNeeded() const override; }; @@ -835,36 +835,36 @@ // attached to regular output sections. class MergeSyntheticSection : public SyntheticSection { public: - void addSection(MergeInputSection *MS); - std::vector Sections; + void addSection(MergeInputSection *ms); + std::vector sections; protected: - MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags, - uint32_t Alignment) - : SyntheticSection(Flags, Type, Alignment, Name) {} + MergeSyntheticSection(StringRef name, uint32_t type, uint64_t flags, + uint32_t alignment) + : SyntheticSection(flags, type, alignment, name) {} }; class MergeTailSection final : public MergeSyntheticSection { public: - MergeTailSection(StringRef Name, uint32_t Type, uint64_t Flags, - uint32_t Alignment); + MergeTailSection(StringRef name, uint32_t type, uint64_t flags, + uint32_t alignment); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; void finalizeContents() override; private: - llvm::StringTableBuilder Builder; + llvm::StringTableBuilder builder; }; class MergeNoTailSection final : public MergeSyntheticSection { public: - MergeNoTailSection(StringRef Name, uint32_t Type, uint64_t Flags, - uint32_t Alignment) - : MergeSyntheticSection(Name, Type, Flags, Alignment) {} + MergeNoTailSection(StringRef name, uint32_t type, uint64_t flags, + uint32_t alignment) + : MergeSyntheticSection(name, type, flags, alignment) {} - size_t getSize() const override { return Size; } - void writeTo(uint8_t *Buf) override; + size_t getSize() const override { return size; } + void writeTo(uint8_t *buf) override; void finalizeContents() override; private: @@ -873,18 +873,18 @@ // because DenseMap also uses lower bits to determine a bucket ID. // If we use lower bits, it significantly increases the probability of // hash collisons. - size_t getShardId(uint32_t Hash) { - assert((Hash >> 31) == 0); - return Hash >> (31 - llvm::countTrailingZeros(NumShards)); + size_t getShardId(uint32_t hash) { + assert((hash >> 31) == 0); + return hash >> (31 - llvm::countTrailingZeros(numShards)); } // Section size - size_t Size; + size_t size; // String table contents - constexpr static size_t NumShards = 32; - std::vector Shards; - size_t ShardOffsets[NumShards]; + constexpr static size_t numShards = 32; + std::vector shards; + size_t shardOffsets[numShards]; }; // .MIPS.abiflags section. @@ -895,12 +895,12 @@ public: static MipsAbiFlagsSection *create(); - MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags); + MipsAbiFlagsSection(Elf_Mips_ABIFlags flags); size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); } - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; private: - Elf_Mips_ABIFlags Flags; + Elf_Mips_ABIFlags flags; }; // .MIPS.options section. @@ -911,15 +911,15 @@ public: static MipsOptionsSection *create(); - MipsOptionsSection(Elf_Mips_RegInfo Reginfo); - void writeTo(uint8_t *Buf) override; + MipsOptionsSection(Elf_Mips_RegInfo reginfo); + void writeTo(uint8_t *buf) override; size_t getSize() const override { return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); } private: - Elf_Mips_RegInfo Reginfo; + Elf_Mips_RegInfo reginfo; }; // MIPS .reginfo section. @@ -929,12 +929,12 @@ public: static MipsReginfoSection *create(); - MipsReginfoSection(Elf_Mips_RegInfo Reginfo); + MipsReginfoSection(Elf_Mips_RegInfo reginfo); size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); } - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; private: - Elf_Mips_RegInfo Reginfo; + Elf_Mips_RegInfo reginfo; }; // This is a MIPS specific section to hold a space within the data segment @@ -944,8 +944,8 @@ class MipsRldMapSection : public SyntheticSection { public: MipsRldMapSection(); - size_t getSize() const override { return Config->Wordsize; } - void writeTo(uint8_t *Buf) override {} + size_t getSize() const override { return config->wordsize; } + void writeTo(uint8_t *buf) override {} }; // Representation of the combined .ARM.Exidx input sections. We process these @@ -988,38 +988,38 @@ // Add an input section to the ARMExidxSyntheticSection. Returns whether the // section needs to be removed from the main input section list. - bool addSection(InputSection *IS); + bool addSection(InputSection *isec); - size_t getSize() const override { return Size; } - void writeTo(uint8_t *Buf) override; - bool isNeeded() const override { return !Empty; } + size_t getSize() const override { return size; } + void writeTo(uint8_t *buf) override; + bool isNeeded() const override { return !empty; } // Sort and remove duplicate entries. void finalizeContents() override; InputSection *getLinkOrderDep() const; - static bool classof(const SectionBase *D); + static bool classof(const SectionBase *d); // Links to the ARMExidxSections so we can transfer the relocations once the // layout is known. - std::vector ExidxSections; + std::vector exidxSections; private: - size_t Size; + size_t size; // Empty if ExecutableSections contains no dependent .ARM.exidx sections. - bool Empty = true; + bool empty = true; // Instead of storing pointers to the .ARM.exidx InputSections from // InputObjects, we store pointers to the executable sections that need // .ARM.exidx sections. We can then use the dependentSections of these to // either find the .ARM.exidx section or know that we need to generate one. - std::vector ExecutableSections; + std::vector executableSections; // The executable InputSection with the highest address to use for the // sentinel. We store separately from ExecutableSections as merging of // duplicate entries may mean this InputSection is removed from // ExecutableSections. - InputSection *Sentinel = nullptr; + InputSection *sentinel = nullptr; }; // A container for one or more linker generated thunks. Instances of these @@ -1027,21 +1027,21 @@ class ThunkSection : public SyntheticSection { public: // ThunkSection in OS, with desired OutSecOff of Off - ThunkSection(OutputSection *OS, uint64_t Off); + ThunkSection(OutputSection *os, uint64_t off); // Add a newly created Thunk to this container: // Thunk is given offset from start of this InputSection // Thunk defines a symbol in this InputSection that can be used as target // of a relocation - void addThunk(Thunk *T); - size_t getSize() const override { return Size; } - void writeTo(uint8_t *Buf) override; + void addThunk(Thunk *t); + size_t getSize() const override { return size; } + void writeTo(uint8_t *buf) override; InputSection *getTargetInputSection() const; bool assignOffsets(); private: - std::vector Thunks; - size_t Size = 0; + std::vector thunks; + size_t size = 0; }; // Used to compute OutSecOff of .got2 in each object file. This is needed to @@ -1052,7 +1052,7 @@ size_t getSize() const override { return 0; } bool isNeeded() const override; void finalizeContents() override; - void writeTo(uint8_t *Buf) override {} + void writeTo(uint8_t *buf) override {} }; // This section is used to store the addresses of functions that are called @@ -1063,15 +1063,15 @@ class PPC64LongBranchTargetSection final : public SyntheticSection { public: PPC64LongBranchTargetSection(); - void addEntry(Symbol &Sym); + void addEntry(Symbol &sym); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; bool isNeeded() const override; - void finalizeContents() override { Finalized = true; } + void finalizeContents() override { finalized = true; } private: - std::vector Entries; - bool Finalized = false; + std::vector entries; + bool finalized = false; }; template @@ -1079,7 +1079,7 @@ public: PartitionElfHeaderSection(); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; }; template @@ -1087,7 +1087,7 @@ public: PartitionProgramHeadersSection(); size_t getSize() const override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; }; class PartitionIndexSection : public SyntheticSection { @@ -1095,7 +1095,7 @@ PartitionIndexSection(); size_t getSize() const override; void finalizeContents() override; - void writeTo(uint8_t *Buf) override; + void writeTo(uint8_t *buf) override; }; // Create a dummy .sdata for __global_pointer$ if .sdata does not exist. @@ -1104,7 +1104,7 @@ RISCVSdataSection(); size_t getSize() const override { return 0; } bool isNeeded() const override; - void writeTo(uint8_t *Buf) override {} + void writeTo(uint8_t *buf) override {} }; InputSection *createInterpSection(); @@ -1112,75 +1112,75 @@ template void splitSections(); void mergeSections(); -template void writeEhdr(uint8_t *Buf, Partition &Part); -template void writePhdrs(uint8_t *Buf, Partition &Part); +template void writeEhdr(uint8_t *buf, Partition &part); +template void writePhdrs(uint8_t *buf, Partition &part); -Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, - uint64_t Size, InputSectionBase &Section); +Defined *addSyntheticLocal(StringRef name, uint8_t type, uint64_t value, + uint64_t size, InputSectionBase §ion); -void addVerneed(Symbol *SS); +void addVerneed(Symbol *ss); // Linker generated per-partition sections. struct Partition { - StringRef Name; - uint64_t NameStrTab; + StringRef name; + uint64_t nameStrTab; - SyntheticSection *ElfHeader; - SyntheticSection *ProgramHeaders; - std::vector Phdrs; - - ARMExidxSyntheticSection *ARMExidx; - BuildIdSection *BuildId; - SyntheticSection *Dynamic; - StringTableSection *DynStrTab; - SymbolTableBaseSection *DynSymTab; - EhFrameHeader *EhFrameHdr; - EhFrameSection *EhFrame; - GnuHashTableSection *GnuHashTab; - HashTableSection *HashTab; - RelocationBaseSection *RelaDyn; - RelrBaseSection *RelrDyn; - VersionDefinitionSection *VerDef; - SyntheticSection *VerNeed; - VersionTableSection *VerSym; + SyntheticSection *elfHeader; + SyntheticSection *programHeaders; + std::vector phdrs; + + ARMExidxSyntheticSection *armExidx; + BuildIdSection *buildId; + SyntheticSection *dynamic; + StringTableSection *dynStrTab; + SymbolTableBaseSection *dynSymTab; + EhFrameHeader *ehFrameHdr; + EhFrameSection *ehFrame; + GnuHashTableSection *gnuHashTab; + HashTableSection *hashTab; + RelocationBaseSection *relaDyn; + RelrBaseSection *relrDyn; + VersionDefinitionSection *verDef; + SyntheticSection *verNeed; + VersionTableSection *verSym; - unsigned getNumber() const { return this - &Partitions[0] + 1; } + unsigned getNumber() const { return this - &partitions[0] + 1; } }; -extern Partition *Main; +extern Partition *mainPart; inline Partition &SectionBase::getPartition() const { assert(isLive()); - return Partitions[Partition - 1]; + return partitions[partition - 1]; } // Linker generated sections which can be used as inputs and are not specific to // a partition. struct InStruct { - InputSection *ARMAttributes; - BssSection *Bss; - BssSection *BssRelRo; - GotSection *Got; - GotPltSection *GotPlt; - IgotPltSection *IgotPlt; - PPC64LongBranchTargetSection *PPC64LongBranchTarget; - MipsGotSection *MipsGot; - MipsRldMapSection *MipsRldMap; - SyntheticSection *PartEnd; - SyntheticSection *PartIndex; - PltSection *Plt; - PltSection *Iplt; - PPC32Got2Section *PPC32Got2; - RISCVSdataSection *RISCVSdata; - RelocationBaseSection *RelaPlt; - RelocationBaseSection *RelaIplt; - StringTableSection *ShStrTab; - StringTableSection *StrTab; - SymbolTableBaseSection *SymTab; - SymtabShndxSection *SymTabShndx; + InputSection *armAttributes; + BssSection *bss; + BssSection *bssRelRo; + GotSection *got; + GotPltSection *gotPlt; + IgotPltSection *igotPlt; + PPC64LongBranchTargetSection *ppc64LongBranchTarget; + MipsGotSection *mipsGot; + MipsRldMapSection *mipsRldMap; + SyntheticSection *partEnd; + SyntheticSection *partIndex; + PltSection *plt; + PltSection *iplt; + PPC32Got2Section *ppc32Got2; + RISCVSdataSection *riscvSdata; + RelocationBaseSection *relaPlt; + RelocationBaseSection *relaIplt; + StringTableSection *shStrTab; + StringTableSection *strTab; + SymbolTableBaseSection *symTab; + SymtabShndxSection *symTabShndx; }; -extern InStruct In; +extern InStruct in; } // namespace elf } // namespace lld Index: lld/trunk/ELF/SyntheticSections.cpp =================================================================== --- lld/trunk/ELF/SyntheticSections.cpp +++ lld/trunk/ELF/SyntheticSections.cpp @@ -52,17 +52,17 @@ using llvm::support::endian::write32le; using llvm::support::endian::write64le; -constexpr size_t MergeNoTailSection::NumShards; +constexpr size_t MergeNoTailSection::numShards; -static uint64_t readUint(uint8_t *Buf) { - return Config->Is64 ? read64(Buf) : read32(Buf); +static uint64_t readUint(uint8_t *buf) { + return config->is64 ? read64(buf) : read32(buf); } -static void writeUint(uint8_t *Buf, uint64_t Val) { - if (Config->Is64) - write64(Buf, Val); +static void writeUint(uint8_t *buf, uint64_t val) { + if (config->is64) + write64(buf, val); else - write32(Buf, Val); + write32(buf, val); } // Returns an LLD version string. @@ -70,12 +70,12 @@ // Check LLD_VERSION first for ease of testing. // You can get consistent output by using the environment variable. // This is only for testing. - StringRef S = getenv("LLD_VERSION"); - if (S.empty()) - S = Saver.save(Twine("Linker: ") + getLLDVersion()); + StringRef s = getenv("LLD_VERSION"); + if (s.empty()) + s = Saver.save(Twine("Linker: ") + getLLDVersion()); // +1 to include the terminating '\0'. - return {(const uint8_t *)S.data(), S.size() + 1}; + return {(const uint8_t *)s.data(), s.size() + 1}; } // Creates a .comment section containing LLD version info. @@ -89,79 +89,79 @@ // .MIPS.abiflags section. template -MipsAbiFlagsSection::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags) +MipsAbiFlagsSection::MipsAbiFlagsSection(Elf_Mips_ABIFlags flags) : SyntheticSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ".MIPS.abiflags"), - Flags(Flags) { - this->Entsize = sizeof(Elf_Mips_ABIFlags); + flags(flags) { + this->entsize = sizeof(Elf_Mips_ABIFlags); } -template void MipsAbiFlagsSection::writeTo(uint8_t *Buf) { - memcpy(Buf, &Flags, sizeof(Flags)); +template void MipsAbiFlagsSection::writeTo(uint8_t *buf) { + memcpy(buf, &flags, sizeof(flags)); } template MipsAbiFlagsSection *MipsAbiFlagsSection::create() { - Elf_Mips_ABIFlags Flags = {}; - bool Create = false; + Elf_Mips_ABIFlags flags = {}; + bool create = false; - for (InputSectionBase *Sec : InputSections) { - if (Sec->Type != SHT_MIPS_ABIFLAGS) + for (InputSectionBase *sec : inputSections) { + if (sec->type != SHT_MIPS_ABIFLAGS) continue; - Sec->markDead(); - Create = true; + sec->markDead(); + create = true; - std::string Filename = toString(Sec->File); - const size_t Size = Sec->data().size(); + std::string filename = toString(sec->file); + const size_t size = sec->data().size(); // Older version of BFD (such as the default FreeBSD linker) concatenate // .MIPS.abiflags instead of merging. To allow for this case (or potential // zero padding) we ignore everything after the first Elf_Mips_ABIFlags - if (Size < sizeof(Elf_Mips_ABIFlags)) { - error(Filename + ": invalid size of .MIPS.abiflags section: got " + - Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); + if (size < sizeof(Elf_Mips_ABIFlags)) { + error(filename + ": invalid size of .MIPS.abiflags section: got " + + Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); return nullptr; } - auto *S = reinterpret_cast(Sec->data().data()); - if (S->version != 0) { - error(Filename + ": unexpected .MIPS.abiflags version " + - Twine(S->version)); + auto *s = reinterpret_cast(sec->data().data()); + if (s->version != 0) { + error(filename + ": unexpected .MIPS.abiflags version " + + Twine(s->version)); return nullptr; } // LLD checks ISA compatibility in calcMipsEFlags(). Here we just // select the highest number of ISA/Rev/Ext. - Flags.isa_level = std::max(Flags.isa_level, S->isa_level); - Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); - Flags.isa_ext = std::max(Flags.isa_ext, S->isa_ext); - Flags.gpr_size = std::max(Flags.gpr_size, S->gpr_size); - Flags.cpr1_size = std::max(Flags.cpr1_size, S->cpr1_size); - Flags.cpr2_size = std::max(Flags.cpr2_size, S->cpr2_size); - Flags.ases |= S->ases; - Flags.flags1 |= S->flags1; - Flags.flags2 |= S->flags2; - Flags.fp_abi = elf::getMipsFpAbiFlag(Flags.fp_abi, S->fp_abi, Filename); + flags.isa_level = std::max(flags.isa_level, s->isa_level); + flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); + flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); + flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); + flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); + flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); + flags.ases |= s->ases; + flags.flags1 |= s->flags1; + flags.flags2 |= s->flags2; + flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); }; - if (Create) - return make>(Flags); + if (create) + return make>(flags); return nullptr; } // .MIPS.options section. template -MipsOptionsSection::MipsOptionsSection(Elf_Mips_RegInfo Reginfo) +MipsOptionsSection::MipsOptionsSection(Elf_Mips_RegInfo reginfo) : SyntheticSection(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"), - Reginfo(Reginfo) { - this->Entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); + reginfo(reginfo) { + this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); } -template void MipsOptionsSection::writeTo(uint8_t *Buf) { - auto *Options = reinterpret_cast(Buf); - Options->kind = ODK_REGINFO; - Options->size = getSize(); - - if (!Config->Relocatable) - Reginfo.ri_gp_value = In.MipsGot->getGp(); - memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo)); +template void MipsOptionsSection::writeTo(uint8_t *buf) { + auto *options = reinterpret_cast(buf); + options->kind = ODK_REGINFO; + options->size = getSize(); + + if (!config->relocatable) + reginfo.ri_gp_value = in.mipsGot->getGp(); + memcpy(buf + sizeof(Elf_Mips_Options), ®info, sizeof(reginfo)); } template @@ -170,55 +170,55 @@ if (!ELFT::Is64Bits) return nullptr; - std::vector Sections; - for (InputSectionBase *Sec : InputSections) - if (Sec->Type == SHT_MIPS_OPTIONS) - Sections.push_back(Sec); + std::vector sections; + for (InputSectionBase *sec : inputSections) + if (sec->type == SHT_MIPS_OPTIONS) + sections.push_back(sec); - if (Sections.empty()) + if (sections.empty()) return nullptr; - Elf_Mips_RegInfo Reginfo = {}; - for (InputSectionBase *Sec : Sections) { - Sec->markDead(); - - std::string Filename = toString(Sec->File); - ArrayRef D = Sec->data(); - - while (!D.empty()) { - if (D.size() < sizeof(Elf_Mips_Options)) { - error(Filename + ": invalid size of .MIPS.options section"); + Elf_Mips_RegInfo reginfo = {}; + for (InputSectionBase *sec : sections) { + sec->markDead(); + + std::string filename = toString(sec->file); + ArrayRef d = sec->data(); + + while (!d.empty()) { + if (d.size() < sizeof(Elf_Mips_Options)) { + error(filename + ": invalid size of .MIPS.options section"); break; } - auto *Opt = reinterpret_cast(D.data()); - if (Opt->kind == ODK_REGINFO) { - Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask; - Sec->getFile()->MipsGp0 = Opt->getRegInfo().ri_gp_value; + auto *opt = reinterpret_cast(d.data()); + if (opt->kind == ODK_REGINFO) { + reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; + sec->getFile()->mipsGp0 = opt->getRegInfo().ri_gp_value; break; } - if (!Opt->size) - fatal(Filename + ": zero option descriptor size"); - D = D.slice(Opt->size); + if (!opt->size) + fatal(filename + ": zero option descriptor size"); + d = d.slice(opt->size); } }; - return make>(Reginfo); + return make>(reginfo); } // MIPS .reginfo section. template -MipsReginfoSection::MipsReginfoSection(Elf_Mips_RegInfo Reginfo) +MipsReginfoSection::MipsReginfoSection(Elf_Mips_RegInfo reginfo) : SyntheticSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ".reginfo"), - Reginfo(Reginfo) { - this->Entsize = sizeof(Elf_Mips_RegInfo); + reginfo(reginfo) { + this->entsize = sizeof(Elf_Mips_RegInfo); } -template void MipsReginfoSection::writeTo(uint8_t *Buf) { - if (!Config->Relocatable) - Reginfo.ri_gp_value = In.MipsGot->getGp(); - memcpy(Buf, &Reginfo, sizeof(Reginfo)); +template void MipsReginfoSection::writeTo(uint8_t *buf) { + if (!config->relocatable) + reginfo.ri_gp_value = in.mipsGot->getGp(); + memcpy(buf, ®info, sizeof(reginfo)); } template @@ -227,53 +227,53 @@ if (ELFT::Is64Bits) return nullptr; - std::vector Sections; - for (InputSectionBase *Sec : InputSections) - if (Sec->Type == SHT_MIPS_REGINFO) - Sections.push_back(Sec); + std::vector sections; + for (InputSectionBase *sec : inputSections) + if (sec->type == SHT_MIPS_REGINFO) + sections.push_back(sec); - if (Sections.empty()) + if (sections.empty()) return nullptr; - Elf_Mips_RegInfo Reginfo = {}; - for (InputSectionBase *Sec : Sections) { - Sec->markDead(); + Elf_Mips_RegInfo reginfo = {}; + for (InputSectionBase *sec : sections) { + sec->markDead(); - if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) { - error(toString(Sec->File) + ": invalid size of .reginfo section"); + if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { + error(toString(sec->file) + ": invalid size of .reginfo section"); return nullptr; } - auto *R = reinterpret_cast(Sec->data().data()); - Reginfo.ri_gprmask |= R->ri_gprmask; - Sec->getFile()->MipsGp0 = R->ri_gp_value; + auto *r = reinterpret_cast(sec->data().data()); + reginfo.ri_gprmask |= r->ri_gprmask; + sec->getFile()->mipsGp0 = r->ri_gp_value; }; - return make>(Reginfo); + return make>(reginfo); } InputSection *elf::createInterpSection() { // StringSaver guarantees that the returned string ends with '\0'. - StringRef S = Saver.save(Config->DynamicLinker); - ArrayRef Contents = {(const uint8_t *)S.data(), S.size() + 1}; + StringRef s = Saver.save(config->dynamicLinker); + ArrayRef contents = {(const uint8_t *)s.data(), s.size() + 1}; - auto *Sec = make(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, Contents, + auto *sec = make(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents, ".interp"); - Sec->markLive(); - return Sec; + sec->markLive(); + return sec; } -Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, - uint64_t Size, InputSectionBase &Section) { - auto *S = make(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type, - Value, Size, &Section); - if (In.SymTab) - In.SymTab->addSymbol(S); - return S; +Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value, + uint64_t size, InputSectionBase §ion) { + auto *s = make(section.file, name, STB_LOCAL, STV_DEFAULT, type, + value, size, §ion); + if (in.symTab) + in.symTab->addSymbol(s); + return s; } static size_t getHashSize() { - switch (Config->BuildId) { + switch (config->buildId) { case BuildIdKind::Fast: return 8; case BuildIdKind::Md5: @@ -282,7 +282,7 @@ case BuildIdKind::Sha1: return 20; case BuildIdKind::Hexstring: - return Config->BuildIdVector.size(); + return config->buildIdVector.size(); default: llvm_unreachable("unknown BuildIdKind"); } @@ -304,45 +304,45 @@ : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, 4, ".note.gnu.property") {} -void GnuPropertySection::writeTo(uint8_t *Buf) { - uint32_t FeatureAndType = Config->EMachine == EM_AARCH64 +void GnuPropertySection::writeTo(uint8_t *buf) { + uint32_t featureAndType = config->emachine == EM_AARCH64 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND : GNU_PROPERTY_X86_FEATURE_1_AND; - write32(Buf, 4); // Name size - write32(Buf + 4, Config->Is64 ? 16 : 12); // Content size - write32(Buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type - memcpy(Buf + 12, "GNU", 4); // Name string - write32(Buf + 16, FeatureAndType); // Feature type - write32(Buf + 20, 4); // Feature size - write32(Buf + 24, Config->AndFeatures); // Feature flags - if (Config->Is64) - write32(Buf + 28, 0); // Padding + write32(buf, 4); // Name size + write32(buf + 4, config->is64 ? 16 : 12); // Content size + write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type + memcpy(buf + 12, "GNU", 4); // Name string + write32(buf + 16, featureAndType); // Feature type + write32(buf + 20, 4); // Feature size + write32(buf + 24, config->andFeatures); // Feature flags + if (config->is64) + write32(buf + 28, 0); // Padding } -size_t GnuPropertySection::getSize() const { return Config->Is64 ? 32 : 28; } +size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; } BuildIdSection::BuildIdSection() : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"), - HashSize(getHashSize()) {} + hashSize(getHashSize()) {} -void BuildIdSection::writeTo(uint8_t *Buf) { - write32(Buf, 4); // Name size - write32(Buf + 4, HashSize); // Content size - write32(Buf + 8, NT_GNU_BUILD_ID); // Type - memcpy(Buf + 12, "GNU", 4); // Name string - HashBuf = Buf + 16; +void BuildIdSection::writeTo(uint8_t *buf) { + write32(buf, 4); // Name size + write32(buf + 4, hashSize); // Content size + write32(buf + 8, NT_GNU_BUILD_ID); // Type + memcpy(buf + 12, "GNU", 4); // Name string + hashBuf = buf + 16; } -void BuildIdSection::writeBuildId(ArrayRef Buf) { - assert(Buf.size() == HashSize); - memcpy(HashBuf, Buf.data(), HashSize); +void BuildIdSection::writeBuildId(ArrayRef buf) { + assert(buf.size() == hashSize); + memcpy(hashBuf, buf.data(), hashSize); } -BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment) - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) { - this->Bss = true; - this->Size = Size; +BssSection::BssSection(StringRef name, uint64_t size, uint32_t alignment) + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, alignment, name) { + this->bss = true; + this->size = size; } EhFrameSection::EhFrameSection() @@ -352,48 +352,48 @@ // CIE records from input object files are uniquified by their contents // and where their relocations point to. template -CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef Rels) { - Symbol *Personality = nullptr; - unsigned FirstRelI = Cie.FirstRelocation; - if (FirstRelI != (unsigned)-1) - Personality = - &Cie.Sec->template getFile()->getRelocTargetSym(Rels[FirstRelI]); +CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef rels) { + Symbol *personality = nullptr; + unsigned firstRelI = cie.firstRelocation; + if (firstRelI != (unsigned)-1) + personality = + &cie.sec->template getFile()->getRelocTargetSym(rels[firstRelI]); // Search for an existing CIE by CIE contents/relocation target pair. - CieRecord *&Rec = CieMap[{Cie.data(), Personality}]; + CieRecord *&rec = cieMap[{cie.data(), personality}]; // If not found, create a new one. - if (!Rec) { - Rec = make(); - Rec->Cie = &Cie; - CieRecords.push_back(Rec); + if (!rec) { + rec = make(); + rec->cie = &cie; + cieRecords.push_back(rec); } - return Rec; + return rec; } // There is one FDE per function. Returns true if a given FDE // points to a live function. template -bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef Rels) { - auto *Sec = cast(Fde.Sec); - unsigned FirstRelI = Fde.FirstRelocation; +bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef rels) { + auto *sec = cast(fde.sec); + unsigned firstRelI = fde.firstRelocation; // An FDE should point to some function because FDEs are to describe // functions. That's however not always the case due to an issue of // ld.gold with -r. ld.gold may discard only functions and leave their // corresponding FDEs, which results in creating bad .eh_frame sections. // To deal with that, we ignore such FDEs. - if (FirstRelI == (unsigned)-1) + if (firstRelI == (unsigned)-1) return false; - const RelTy &Rel = Rels[FirstRelI]; - Symbol &B = Sec->template getFile()->getRelocTargetSym(Rel); + const RelTy &rel = rels[firstRelI]; + Symbol &b = sec->template getFile()->getRelocTargetSym(rel); // FDEs for garbage-collected or merged-by-ICF sections, or sections in // another partition, are dead. - if (auto *D = dyn_cast(&B)) - if (SectionBase *Sec = D->Section) - return Sec->Partition == Partition; + if (auto *d = dyn_cast(&b)) + if (SectionBase *sec = d->section) + return sec->partition == partition; return false; } @@ -402,73 +402,73 @@ // a list of FDEs. This function searches an existing CIE or create a new // one and associates FDEs to the CIE. template -void EhFrameSection::addSectionAux(EhInputSection *Sec, ArrayRef Rels) { - OffsetToCie.clear(); - for (EhSectionPiece &Piece : Sec->Pieces) { +void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef rels) { + offsetToCie.clear(); + for (EhSectionPiece &piece : sec->pieces) { // The empty record is the end marker. - if (Piece.Size == 4) + if (piece.size == 4) return; - size_t Offset = Piece.InputOff; - uint32_t ID = read32(Piece.data().data() + 4); - if (ID == 0) { - OffsetToCie[Offset] = addCie(Piece, Rels); + size_t offset = piece.inputOff; + uint32_t id = read32(piece.data().data() + 4); + if (id == 0) { + offsetToCie[offset] = addCie(piece, rels); continue; } - uint32_t CieOffset = Offset + 4 - ID; - CieRecord *Rec = OffsetToCie[CieOffset]; - if (!Rec) - fatal(toString(Sec) + ": invalid CIE reference"); + uint32_t cieOffset = offset + 4 - id; + CieRecord *rec = offsetToCie[cieOffset]; + if (!rec) + fatal(toString(sec) + ": invalid CIE reference"); - if (!isFdeLive(Piece, Rels)) + if (!isFdeLive(piece, rels)) continue; - Rec->Fdes.push_back(&Piece); - NumFdes++; + rec->fdes.push_back(&piece); + numFdes++; } } -template void EhFrameSection::addSection(InputSectionBase *C) { - auto *Sec = cast(C); - Sec->Parent = this; +template void EhFrameSection::addSection(InputSectionBase *c) { + auto *sec = cast(c); + sec->parent = this; - Alignment = std::max(Alignment, Sec->Alignment); - Sections.push_back(Sec); + alignment = std::max(alignment, sec->alignment); + sections.push_back(sec); - for (auto *DS : Sec->DependentSections) - DependentSections.push_back(DS); + for (auto *ds : sec->dependentSections) + dependentSections.push_back(ds); - if (Sec->Pieces.empty()) + if (sec->pieces.empty()) return; - if (Sec->AreRelocsRela) - addSectionAux(Sec, Sec->template relas()); + if (sec->areRelocsRela) + addSectionAux(sec, sec->template relas()); else - addSectionAux(Sec, Sec->template rels()); + addSectionAux(sec, sec->template rels()); } -static void writeCieFde(uint8_t *Buf, ArrayRef D) { - memcpy(Buf, D.data(), D.size()); +static void writeCieFde(uint8_t *buf, ArrayRef d) { + memcpy(buf, d.data(), d.size()); - size_t Aligned = alignTo(D.size(), Config->Wordsize); + size_t aligned = alignTo(d.size(), config->wordsize); // Zero-clear trailing padding if it exists. - memset(Buf + D.size(), 0, Aligned - D.size()); + memset(buf + d.size(), 0, aligned - d.size()); // Fix the size field. -4 since size does not include the size field itself. - write32(Buf, Aligned - 4); + write32(buf, aligned - 4); } void EhFrameSection::finalizeContents() { - assert(!this->Size); // Not finalized. - size_t Off = 0; - for (CieRecord *Rec : CieRecords) { - Rec->Cie->OutputOff = Off; - Off += alignTo(Rec->Cie->Size, Config->Wordsize); - - for (EhSectionPiece *Fde : Rec->Fdes) { - Fde->OutputOff = Off; - Off += alignTo(Fde->Size, Config->Wordsize); + assert(!this->size); // Not finalized. + size_t off = 0; + for (CieRecord *rec : cieRecords) { + rec->cie->outputOff = off; + off += alignTo(rec->cie->size, config->wordsize); + + for (EhSectionPiece *fde : rec->fdes) { + fde->outputOff = off; + off += alignTo(fde->size, config->wordsize); } } @@ -476,376 +476,376 @@ // Call Frame Information records. glibc unwind-dw2-fde.c // classify_object_over_fdes expects there is a CIE record length 0 as a // terminator. Thus we add one unconditionally. - Off += 4; + off += 4; - this->Size = Off; + this->size = off; } // Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table // to get an FDE from an address to which FDE is applied. This function // returns a list of such pairs. std::vector EhFrameSection::getFdeData() const { - uint8_t *Buf = Out::BufferStart + getParent()->Offset + OutSecOff; - std::vector Ret; + uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; + std::vector ret; - uint64_t VA = getPartition().EhFrameHdr->getVA(); - for (CieRecord *Rec : CieRecords) { - uint8_t Enc = getFdeEncoding(Rec->Cie); - for (EhSectionPiece *Fde : Rec->Fdes) { - uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); - uint64_t FdeVA = getParent()->Addr + Fde->OutputOff; - if (!isInt<32>(Pc - VA)) - fatal(toString(Fde->Sec) + ": PC offset is too large: 0x" + - Twine::utohexstr(Pc - VA)); - Ret.push_back({uint32_t(Pc - VA), uint32_t(FdeVA - VA)}); + uint64_t va = getPartition().ehFrameHdr->getVA(); + for (CieRecord *rec : cieRecords) { + uint8_t enc = getFdeEncoding(rec->cie); + for (EhSectionPiece *fde : rec->fdes) { + uint64_t pc = getFdePc(buf, fde->outputOff, enc); + uint64_t fdeVA = getParent()->addr + fde->outputOff; + if (!isInt<32>(pc - va)) + fatal(toString(fde->sec) + ": PC offset is too large: 0x" + + Twine::utohexstr(pc - va)); + ret.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)}); } } // Sort the FDE list by their PC and uniqueify. Usually there is only // one FDE for a PC (i.e. function), but if ICF merges two functions // into one, there can be more than one FDEs pointing to the address. - auto Less = [](const FdeData &A, const FdeData &B) { - return A.PcRel < B.PcRel; + auto less = [](const FdeData &a, const FdeData &b) { + return a.pcRel < b.pcRel; }; - llvm::stable_sort(Ret, Less); - auto Eq = [](const FdeData &A, const FdeData &B) { - return A.PcRel == B.PcRel; + llvm::stable_sort(ret, less); + auto eq = [](const FdeData &a, const FdeData &b) { + return a.pcRel == b.pcRel; }; - Ret.erase(std::unique(Ret.begin(), Ret.end(), Eq), Ret.end()); + ret.erase(std::unique(ret.begin(), ret.end(), eq), ret.end()); - return Ret; + return ret; } -static uint64_t readFdeAddr(uint8_t *Buf, int Size) { - switch (Size) { +static uint64_t readFdeAddr(uint8_t *buf, int size) { + switch (size) { case DW_EH_PE_udata2: - return read16(Buf); + return read16(buf); case DW_EH_PE_sdata2: - return (int16_t)read16(Buf); + return (int16_t)read16(buf); case DW_EH_PE_udata4: - return read32(Buf); + return read32(buf); case DW_EH_PE_sdata4: - return (int32_t)read32(Buf); + return (int32_t)read32(buf); case DW_EH_PE_udata8: case DW_EH_PE_sdata8: - return read64(Buf); + return read64(buf); case DW_EH_PE_absptr: - return readUint(Buf); + return readUint(buf); } fatal("unknown FDE size encoding"); } // Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to. // We need it to create .eh_frame_hdr section. -uint64_t EhFrameSection::getFdePc(uint8_t *Buf, size_t FdeOff, - uint8_t Enc) const { +uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff, + uint8_t enc) const { // The starting address to which this FDE applies is // stored at FDE + 8 byte. - size_t Off = FdeOff + 8; - uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0xf); - if ((Enc & 0x70) == DW_EH_PE_absptr) - return Addr; - if ((Enc & 0x70) == DW_EH_PE_pcrel) - return Addr + getParent()->Addr + Off; + size_t off = fdeOff + 8; + uint64_t addr = readFdeAddr(buf + off, enc & 0xf); + if ((enc & 0x70) == DW_EH_PE_absptr) + return addr; + if ((enc & 0x70) == DW_EH_PE_pcrel) + return addr + getParent()->addr + off; fatal("unknown FDE size relative encoding"); } -void EhFrameSection::writeTo(uint8_t *Buf) { +void EhFrameSection::writeTo(uint8_t *buf) { // Write CIE and FDE records. - for (CieRecord *Rec : CieRecords) { - size_t CieOffset = Rec->Cie->OutputOff; - writeCieFde(Buf + CieOffset, Rec->Cie->data()); - - for (EhSectionPiece *Fde : Rec->Fdes) { - size_t Off = Fde->OutputOff; - writeCieFde(Buf + Off, Fde->data()); + for (CieRecord *rec : cieRecords) { + size_t cieOffset = rec->cie->outputOff; + writeCieFde(buf + cieOffset, rec->cie->data()); + + for (EhSectionPiece *fde : rec->fdes) { + size_t off = fde->outputOff; + writeCieFde(buf + off, fde->data()); // FDE's second word should have the offset to an associated CIE. // Write it. - write32(Buf + Off + 4, Off + 4 - CieOffset); + write32(buf + off + 4, off + 4 - cieOffset); } } // Apply relocations. .eh_frame section contents are not contiguous // in the output buffer, but relocateAlloc() still works because // getOffset() takes care of discontiguous section pieces. - for (EhInputSection *S : Sections) - S->relocateAlloc(Buf, nullptr); + for (EhInputSection *s : sections) + s->relocateAlloc(buf, nullptr); - if (getPartition().EhFrameHdr && getPartition().EhFrameHdr->getParent()) - getPartition().EhFrameHdr->write(); + if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent()) + getPartition().ehFrameHdr->write(); } GotSection::GotSection() - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, ".got") { // PPC64 saves the ElfSym::GlobalOffsetTable .TOC. as the first entry in the // .got. If there are no references to .TOC. in the symbol table, // ElfSym::GlobalOffsetTable will not be defined and we won't need to save // .TOC. in the .got. When it is defined, we increase NumEntries by the number // of entries used to emit ElfSym::GlobalOffsetTable. - if (ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt) - NumEntries += Target->GotHeaderEntriesNum; + if (ElfSym::globalOffsetTable && !target->gotBaseSymInGotPlt) + numEntries += target->gotHeaderEntriesNum; } -void GotSection::addEntry(Symbol &Sym) { - Sym.GotIndex = NumEntries; - ++NumEntries; +void GotSection::addEntry(Symbol &sym) { + sym.gotIndex = numEntries; + ++numEntries; } -bool GotSection::addDynTlsEntry(Symbol &Sym) { - if (Sym.GlobalDynIndex != -1U) +bool GotSection::addDynTlsEntry(Symbol &sym) { + if (sym.globalDynIndex != -1U) return false; - Sym.GlobalDynIndex = NumEntries; + sym.globalDynIndex = numEntries; // Global Dynamic TLS entries take two GOT slots. - NumEntries += 2; + numEntries += 2; return true; } // Reserves TLS entries for a TLS module ID and a TLS block offset. // In total it takes two GOT slots. bool GotSection::addTlsIndex() { - if (TlsIndexOff != uint32_t(-1)) + if (tlsIndexOff != uint32_t(-1)) return false; - TlsIndexOff = NumEntries * Config->Wordsize; - NumEntries += 2; + tlsIndexOff = numEntries * config->wordsize; + numEntries += 2; return true; } -uint64_t GotSection::getGlobalDynAddr(const Symbol &B) const { - return this->getVA() + B.GlobalDynIndex * Config->Wordsize; +uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const { + return this->getVA() + b.globalDynIndex * config->wordsize; } -uint64_t GotSection::getGlobalDynOffset(const Symbol &B) const { - return B.GlobalDynIndex * Config->Wordsize; +uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const { + return b.globalDynIndex * config->wordsize; } void GotSection::finalizeContents() { - Size = NumEntries * Config->Wordsize; + size = numEntries * config->wordsize; } bool GotSection::isNeeded() const { // We need to emit a GOT even if it's empty if there's a relocation that is // relative to GOT(such as GOTOFFREL). - return NumEntries || HasGotOffRel; + return numEntries || hasGotOffRel; } -void GotSection::writeTo(uint8_t *Buf) { +void GotSection::writeTo(uint8_t *buf) { // Buf points to the start of this section's buffer, // whereas InputSectionBase::relocateAlloc() expects its argument // to point to the start of the output section. - Target->writeGotHeader(Buf); - relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size); + target->writeGotHeader(buf); + relocateAlloc(buf - outSecOff, buf - outSecOff + size); } -static uint64_t getMipsPageAddr(uint64_t Addr) { - return (Addr + 0x8000) & ~0xffff; +static uint64_t getMipsPageAddr(uint64_t addr) { + return (addr + 0x8000) & ~0xffff; } -static uint64_t getMipsPageCount(uint64_t Size) { - return (Size + 0xfffe) / 0xffff + 1; +static uint64_t getMipsPageCount(uint64_t size) { + return (size + 0xfffe) / 0xffff + 1; } MipsGotSection::MipsGotSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, ".got") {} -void MipsGotSection::addEntry(InputFile &File, Symbol &Sym, int64_t Addend, - RelExpr Expr) { - FileGot &G = getGot(File); - if (Expr == R_MIPS_GOT_LOCAL_PAGE) { - if (const OutputSection *OS = Sym.getOutputSection()) - G.PagesMap.insert({OS, {}}); +void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend, + RelExpr expr) { + FileGot &g = getGot(file); + if (expr == R_MIPS_GOT_LOCAL_PAGE) { + if (const OutputSection *os = sym.getOutputSection()) + g.pagesMap.insert({os, {}}); else - G.Local16.insert({{nullptr, getMipsPageAddr(Sym.getVA(Addend))}, 0}); - } else if (Sym.isTls()) - G.Tls.insert({&Sym, 0}); - else if (Sym.IsPreemptible && Expr == R_ABS) - G.Relocs.insert({&Sym, 0}); - else if (Sym.IsPreemptible) - G.Global.insert({&Sym, 0}); - else if (Expr == R_MIPS_GOT_OFF32) - G.Local32.insert({{&Sym, Addend}, 0}); + g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(addend))}, 0}); + } else if (sym.isTls()) + g.tls.insert({&sym, 0}); + else if (sym.isPreemptible && expr == R_ABS) + g.relocs.insert({&sym, 0}); + else if (sym.isPreemptible) + g.global.insert({&sym, 0}); + else if (expr == R_MIPS_GOT_OFF32) + g.local32.insert({{&sym, addend}, 0}); else - G.Local16.insert({{&Sym, Addend}, 0}); + g.local16.insert({{&sym, addend}, 0}); } -void MipsGotSection::addDynTlsEntry(InputFile &File, Symbol &Sym) { - getGot(File).DynTlsSymbols.insert({&Sym, 0}); +void MipsGotSection::addDynTlsEntry(InputFile &file, Symbol &sym) { + getGot(file).dynTlsSymbols.insert({&sym, 0}); } -void MipsGotSection::addTlsIndex(InputFile &File) { - getGot(File).DynTlsSymbols.insert({nullptr, 0}); +void MipsGotSection::addTlsIndex(InputFile &file) { + getGot(file).dynTlsSymbols.insert({nullptr, 0}); } size_t MipsGotSection::FileGot::getEntriesNum() const { - return getPageEntriesNum() + Local16.size() + Global.size() + Relocs.size() + - Tls.size() + DynTlsSymbols.size() * 2; + return getPageEntriesNum() + local16.size() + global.size() + relocs.size() + + tls.size() + dynTlsSymbols.size() * 2; } size_t MipsGotSection::FileGot::getPageEntriesNum() const { - size_t Num = 0; - for (const std::pair &P : PagesMap) - Num += P.second.Count; - return Num; + size_t num = 0; + for (const std::pair &p : pagesMap) + num += p.second.count; + return num; } size_t MipsGotSection::FileGot::getIndexedEntriesNum() const { - size_t Count = getPageEntriesNum() + Local16.size() + Global.size(); + size_t count = getPageEntriesNum() + local16.size() + global.size(); // If there are relocation-only entries in the GOT, TLS entries // are allocated after them. TLS entries should be addressable // by 16-bit index so count both reloc-only and TLS entries. - if (!Tls.empty() || !DynTlsSymbols.empty()) - Count += Relocs.size() + Tls.size() + DynTlsSymbols.size() * 2; - return Count; -} - -MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &F) { - if (!F.MipsGotIndex.hasValue()) { - Gots.emplace_back(); - Gots.back().File = &F; - F.MipsGotIndex = Gots.size() - 1; - } - return Gots[*F.MipsGotIndex]; -} - -uint64_t MipsGotSection::getPageEntryOffset(const InputFile *F, - const Symbol &Sym, - int64_t Addend) const { - const FileGot &G = Gots[*F->MipsGotIndex]; - uint64_t Index = 0; - if (const OutputSection *OutSec = Sym.getOutputSection()) { - uint64_t SecAddr = getMipsPageAddr(OutSec->Addr); - uint64_t SymAddr = getMipsPageAddr(Sym.getVA(Addend)); - Index = G.PagesMap.lookup(OutSec).FirstIndex + (SymAddr - SecAddr) / 0xffff; + if (!tls.empty() || !dynTlsSymbols.empty()) + count += relocs.size() + tls.size() + dynTlsSymbols.size() * 2; + return count; +} + +MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &f) { + if (!f.mipsGotIndex.hasValue()) { + gots.emplace_back(); + gots.back().file = &f; + f.mipsGotIndex = gots.size() - 1; + } + return gots[*f.mipsGotIndex]; +} + +uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f, + const Symbol &sym, + int64_t addend) const { + const FileGot &g = gots[*f->mipsGotIndex]; + uint64_t index = 0; + if (const OutputSection *outSec = sym.getOutputSection()) { + uint64_t secAddr = getMipsPageAddr(outSec->addr); + uint64_t symAddr = getMipsPageAddr(sym.getVA(addend)); + index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff; } else { - Index = G.Local16.lookup({nullptr, getMipsPageAddr(Sym.getVA(Addend))}); + index = g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(addend))}); } - return Index * Config->Wordsize; + return index * config->wordsize; } -uint64_t MipsGotSection::getSymEntryOffset(const InputFile *F, const Symbol &S, - int64_t Addend) const { - const FileGot &G = Gots[*F->MipsGotIndex]; - Symbol *Sym = const_cast(&S); - if (Sym->isTls()) - return G.Tls.lookup(Sym) * Config->Wordsize; - if (Sym->IsPreemptible) - return G.Global.lookup(Sym) * Config->Wordsize; - return G.Local16.lookup({Sym, Addend}) * Config->Wordsize; +uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s, + int64_t addend) const { + const FileGot &g = gots[*f->mipsGotIndex]; + Symbol *sym = const_cast(&s); + if (sym->isTls()) + return g.tls.lookup(sym) * config->wordsize; + if (sym->isPreemptible) + return g.global.lookup(sym) * config->wordsize; + return g.local16.lookup({sym, addend}) * config->wordsize; } -uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *F) const { - const FileGot &G = Gots[*F->MipsGotIndex]; - return G.DynTlsSymbols.lookup(nullptr) * Config->Wordsize; +uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const { + const FileGot &g = gots[*f->mipsGotIndex]; + return g.dynTlsSymbols.lookup(nullptr) * config->wordsize; } -uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *F, - const Symbol &S) const { - const FileGot &G = Gots[*F->MipsGotIndex]; - Symbol *Sym = const_cast(&S); - return G.DynTlsSymbols.lookup(Sym) * Config->Wordsize; +uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f, + const Symbol &s) const { + const FileGot &g = gots[*f->mipsGotIndex]; + Symbol *sym = const_cast(&s); + return g.dynTlsSymbols.lookup(sym) * config->wordsize; } const Symbol *MipsGotSection::getFirstGlobalEntry() const { - if (Gots.empty()) + if (gots.empty()) return nullptr; - const FileGot &PrimGot = Gots.front(); - if (!PrimGot.Global.empty()) - return PrimGot.Global.front().first; - if (!PrimGot.Relocs.empty()) - return PrimGot.Relocs.front().first; + const FileGot &primGot = gots.front(); + if (!primGot.global.empty()) + return primGot.global.front().first; + if (!primGot.relocs.empty()) + return primGot.relocs.front().first; return nullptr; } unsigned MipsGotSection::getLocalEntriesNum() const { - if (Gots.empty()) - return HeaderEntriesNum; - return HeaderEntriesNum + Gots.front().getPageEntriesNum() + - Gots.front().Local16.size(); -} - -bool MipsGotSection::tryMergeGots(FileGot &Dst, FileGot &Src, bool IsPrimary) { - FileGot Tmp = Dst; - set_union(Tmp.PagesMap, Src.PagesMap); - set_union(Tmp.Local16, Src.Local16); - set_union(Tmp.Global, Src.Global); - set_union(Tmp.Relocs, Src.Relocs); - set_union(Tmp.Tls, Src.Tls); - set_union(Tmp.DynTlsSymbols, Src.DynTlsSymbols); + if (gots.empty()) + return headerEntriesNum; + return headerEntriesNum + gots.front().getPageEntriesNum() + + gots.front().local16.size(); +} + +bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) { + FileGot tmp = dst; + set_union(tmp.pagesMap, src.pagesMap); + set_union(tmp.local16, src.local16); + set_union(tmp.global, src.global); + set_union(tmp.relocs, src.relocs); + set_union(tmp.tls, src.tls); + set_union(tmp.dynTlsSymbols, src.dynTlsSymbols); - size_t Count = IsPrimary ? HeaderEntriesNum : 0; - Count += Tmp.getIndexedEntriesNum(); + size_t count = isPrimary ? headerEntriesNum : 0; + count += tmp.getIndexedEntriesNum(); - if (Count * Config->Wordsize > Config->MipsGotSize) + if (count * config->wordsize > config->mipsGotSize) return false; - std::swap(Tmp, Dst); + std::swap(tmp, dst); return true; } void MipsGotSection::finalizeContents() { updateAllocSize(); } bool MipsGotSection::updateAllocSize() { - Size = HeaderEntriesNum * Config->Wordsize; - for (const FileGot &G : Gots) - Size += G.getEntriesNum() * Config->Wordsize; + size = headerEntriesNum * config->wordsize; + for (const FileGot &g : gots) + size += g.getEntriesNum() * config->wordsize; return false; } void MipsGotSection::build() { - if (Gots.empty()) + if (gots.empty()) return; - std::vector MergedGots(1); + std::vector mergedGots(1); // For each GOT move non-preemptible symbols from the `Global` // to `Local16` list. Preemptible symbol might become non-preemptible // one if, for example, it gets a related copy relocation. - for (FileGot &Got : Gots) { - for (auto &P: Got.Global) - if (!P.first->IsPreemptible) - Got.Local16.insert({{P.first, 0}, 0}); - Got.Global.remove_if([&](const std::pair &P) { - return !P.first->IsPreemptible; + for (FileGot &got : gots) { + for (auto &p: got.global) + if (!p.first->isPreemptible) + got.local16.insert({{p.first, 0}, 0}); + got.global.remove_if([&](const std::pair &p) { + return !p.first->isPreemptible; }); } // For each GOT remove "reloc-only" entry if there is "global" // entry for the same symbol. And add local entries which indexed // using 32-bit value at the end of 16-bit entries. - for (FileGot &Got : Gots) { - Got.Relocs.remove_if([&](const std::pair &P) { - return Got.Global.count(P.first); + for (FileGot &got : gots) { + got.relocs.remove_if([&](const std::pair &p) { + return got.global.count(p.first); }); - set_union(Got.Local16, Got.Local32); - Got.Local32.clear(); + set_union(got.local16, got.local32); + got.local32.clear(); } // Evaluate number of "reloc-only" entries in the resulting GOT. // To do that put all unique "reloc-only" and "global" entries // from all GOTs to the future primary GOT. - FileGot *PrimGot = &MergedGots.front(); - for (FileGot &Got : Gots) { - set_union(PrimGot->Relocs, Got.Global); - set_union(PrimGot->Relocs, Got.Relocs); - Got.Relocs.clear(); + FileGot *primGot = &mergedGots.front(); + for (FileGot &got : gots) { + set_union(primGot->relocs, got.global); + set_union(primGot->relocs, got.relocs); + got.relocs.clear(); } // Evaluate number of "page" entries in each GOT. - for (FileGot &Got : Gots) { - for (std::pair &P : - Got.PagesMap) { - const OutputSection *OS = P.first; - uint64_t SecSize = 0; - for (BaseCommand *Cmd : OS->SectionCommands) { - if (auto *ISD = dyn_cast(Cmd)) - for (InputSection *IS : ISD->Sections) { - uint64_t Off = alignTo(SecSize, IS->Alignment); - SecSize = Off + IS->getSize(); + for (FileGot &got : gots) { + for (std::pair &p : + got.pagesMap) { + const OutputSection *os = p.first; + uint64_t secSize = 0; + for (BaseCommand *cmd : os->sectionCommands) { + if (auto *isd = dyn_cast(cmd)) + for (InputSection *isec : isd->sections) { + uint64_t off = alignTo(secSize, isec->alignment); + secSize = off + isec->getSize(); } } - P.second.Count = getMipsPageCount(SecSize); + p.second.count = getMipsPageCount(secSize); } } @@ -854,128 +854,128 @@ // the primary GOT can be accessed in the most effective way. If it // is not possible, try to fill the last GOT in the list, and finally // create a new GOT if both attempts failed. - for (FileGot &SrcGot : Gots) { - InputFile *File = SrcGot.File; - if (tryMergeGots(MergedGots.front(), SrcGot, true)) { - File->MipsGotIndex = 0; + for (FileGot &srcGot : gots) { + InputFile *file = srcGot.file; + if (tryMergeGots(mergedGots.front(), srcGot, true)) { + file->mipsGotIndex = 0; } else { // If this is the first time we failed to merge with the primary GOT, // MergedGots.back() will also be the primary GOT. We must make sure not // to try to merge again with IsPrimary=false, as otherwise, if the // inputs are just right, we could allow the primary GOT to become 1 or 2 // words too big due to ignoring the header size. - if (MergedGots.size() == 1 || - !tryMergeGots(MergedGots.back(), SrcGot, false)) { - MergedGots.emplace_back(); - std::swap(MergedGots.back(), SrcGot); + if (mergedGots.size() == 1 || + !tryMergeGots(mergedGots.back(), srcGot, false)) { + mergedGots.emplace_back(); + std::swap(mergedGots.back(), srcGot); } - File->MipsGotIndex = MergedGots.size() - 1; + file->mipsGotIndex = mergedGots.size() - 1; } } - std::swap(Gots, MergedGots); + std::swap(gots, mergedGots); // Reduce number of "reloc-only" entries in the primary GOT // by substracting "global" entries exist in the primary GOT. - PrimGot = &Gots.front(); - PrimGot->Relocs.remove_if([&](const std::pair &P) { - return PrimGot->Global.count(P.first); + primGot = &gots.front(); + primGot->relocs.remove_if([&](const std::pair &p) { + return primGot->global.count(p.first); }); // Calculate indexes for each GOT entry. - size_t Index = HeaderEntriesNum; - for (FileGot &Got : Gots) { - Got.StartIndex = &Got == PrimGot ? 0 : Index; - for (std::pair &P : - Got.PagesMap) { + size_t index = headerEntriesNum; + for (FileGot &got : gots) { + got.startIndex = &got == primGot ? 0 : index; + for (std::pair &p : + got.pagesMap) { // For each output section referenced by GOT page relocations calculate // and save into PagesMap an upper bound of MIPS GOT entries required // to store page addresses of local symbols. We assume the worst case - // each 64kb page of the output section has at least one GOT relocation // against it. And take in account the case when the section intersects // page boundaries. - P.second.FirstIndex = Index; - Index += P.second.Count; + p.second.firstIndex = index; + index += p.second.count; } - for (auto &P: Got.Local16) - P.second = Index++; - for (auto &P: Got.Global) - P.second = Index++; - for (auto &P: Got.Relocs) - P.second = Index++; - for (auto &P: Got.Tls) - P.second = Index++; - for (auto &P: Got.DynTlsSymbols) { - P.second = Index; - Index += 2; + for (auto &p: got.local16) + p.second = index++; + for (auto &p: got.global) + p.second = index++; + for (auto &p: got.relocs) + p.second = index++; + for (auto &p: got.tls) + p.second = index++; + for (auto &p: got.dynTlsSymbols) { + p.second = index; + index += 2; } } // Update Symbol::GotIndex field to use this // value later in the `sortMipsSymbols` function. - for (auto &P : PrimGot->Global) - P.first->GotIndex = P.second; - for (auto &P : PrimGot->Relocs) - P.first->GotIndex = P.second; + for (auto &p : primGot->global) + p.first->gotIndex = p.second; + for (auto &p : primGot->relocs) + p.first->gotIndex = p.second; // Create dynamic relocations. - for (FileGot &Got : Gots) { + for (FileGot &got : gots) { // Create dynamic relocations for TLS entries. - for (std::pair &P : Got.Tls) { - Symbol *S = P.first; - uint64_t Offset = P.second * Config->Wordsize; - if (S->IsPreemptible) - Main->RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S); - } - for (std::pair &P : Got.DynTlsSymbols) { - Symbol *S = P.first; - uint64_t Offset = P.second * Config->Wordsize; - if (S == nullptr) { - if (!Config->Pic) + for (std::pair &p : got.tls) { + Symbol *s = p.first; + uint64_t offset = p.second * config->wordsize; + if (s->isPreemptible) + mainPart->relaDyn->addReloc(target->tlsGotRel, this, offset, s); + } + for (std::pair &p : got.dynTlsSymbols) { + Symbol *s = p.first; + uint64_t offset = p.second * config->wordsize; + if (s == nullptr) { + if (!config->isPic) continue; - Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); + mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s); } else { // When building a shared library we still need a dynamic relocation // for the module index. Therefore only checking for // S->IsPreemptible is not sufficient (this happens e.g. for // thread-locals that have been marked as local through a linker script) - if (!S->IsPreemptible && !Config->Pic) + if (!s->isPreemptible && !config->isPic) continue; - Main->RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); + mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s); // However, we can skip writing the TLS offset reloc for non-preemptible // symbols since it is known even in shared libraries - if (!S->IsPreemptible) + if (!s->isPreemptible) continue; - Offset += Config->Wordsize; - Main->RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S); + offset += config->wordsize; + mainPart->relaDyn->addReloc(target->tlsOffsetRel, this, offset, s); } } // Do not create dynamic relocations for non-TLS // entries in the primary GOT. - if (&Got == PrimGot) + if (&got == primGot) continue; // Dynamic relocations for "global" entries. - for (const std::pair &P : Got.Global) { - uint64_t Offset = P.second * Config->Wordsize; - Main->RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first); + for (const std::pair &p : got.global) { + uint64_t offset = p.second * config->wordsize; + mainPart->relaDyn->addReloc(target->relativeRel, this, offset, p.first); } - if (!Config->Pic) + if (!config->isPic) continue; // Dynamic relocations for "local" entries in case of PIC. - for (const std::pair &L : - Got.PagesMap) { - size_t PageCount = L.second.Count; - for (size_t PI = 0; PI < PageCount; ++PI) { - uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize; - Main->RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first, - int64_t(PI * 0x10000)}); + for (const std::pair &l : + got.pagesMap) { + size_t pageCount = l.second.count; + for (size_t pi = 0; pi < pageCount; ++pi) { + uint64_t offset = (l.second.firstIndex + pi) * config->wordsize; + mainPart->relaDyn->addReloc({target->relativeRel, this, offset, l.first, + int64_t(pi * 0x10000)}); } } - for (const std::pair &P : Got.Local16) { - uint64_t Offset = P.second * Config->Wordsize; - Main->RelaDyn->addReloc({Target->RelativeRel, this, Offset, true, - P.first.first, P.first.second}); + for (const std::pair &p : got.local16) { + uint64_t offset = p.second * config->wordsize; + mainPart->relaDyn->addReloc({target->relativeRel, this, offset, true, + p.first.first, p.first.second}); } } } @@ -983,20 +983,20 @@ bool MipsGotSection::isNeeded() const { // We add the .got section to the result for dynamic MIPS target because // its address and properties are mentioned in the .dynamic section. - return !Config->Relocatable; + return !config->relocatable; } -uint64_t MipsGotSection::getGp(const InputFile *F) const { +uint64_t MipsGotSection::getGp(const InputFile *f) const { // For files without related GOT or files refer a primary GOT // returns "common" _gp value. For secondary GOTs calculate // individual _gp values. - if (!F || !F->MipsGotIndex.hasValue() || *F->MipsGotIndex == 0) - return ElfSym::MipsGp->getVA(0); - return getVA() + Gots[*F->MipsGotIndex].StartIndex * Config->Wordsize + + if (!f || !f->mipsGotIndex.hasValue() || *f->mipsGotIndex == 0) + return ElfSym::mipsGp->getVA(0); + return getVA() + gots[*f->mipsGotIndex].startIndex * config->wordsize + 0x7ff0; } -void MipsGotSection::writeTo(uint8_t *Buf) { +void MipsGotSection::writeTo(uint8_t *buf) { // Set the MSB of the second GOT slot. This is not required by any // MIPS ABI documentation, though. // @@ -1011,48 +1011,48 @@ // we've been doing this for years, it is probably a safe bet to // keep doing this for now. We really need to revisit this to see // if we had to do this. - writeUint(Buf + Config->Wordsize, (uint64_t)1 << (Config->Wordsize * 8 - 1)); - for (const FileGot &G : Gots) { - auto Write = [&](size_t I, const Symbol *S, int64_t A) { - uint64_t VA = A; - if (S) - VA = S->getVA(A); - writeUint(Buf + I * Config->Wordsize, VA); + writeUint(buf + config->wordsize, (uint64_t)1 << (config->wordsize * 8 - 1)); + for (const FileGot &g : gots) { + auto write = [&](size_t i, const Symbol *s, int64_t a) { + uint64_t va = a; + if (s) + va = s->getVA(a); + writeUint(buf + i * config->wordsize, va); }; // Write 'page address' entries to the local part of the GOT. - for (const std::pair &L : - G.PagesMap) { - size_t PageCount = L.second.Count; - uint64_t FirstPageAddr = getMipsPageAddr(L.first->Addr); - for (size_t PI = 0; PI < PageCount; ++PI) - Write(L.second.FirstIndex + PI, nullptr, FirstPageAddr + PI * 0x10000); + for (const std::pair &l : + g.pagesMap) { + size_t pageCount = l.second.count; + uint64_t firstPageAddr = getMipsPageAddr(l.first->addr); + for (size_t pi = 0; pi < pageCount; ++pi) + write(l.second.firstIndex + pi, nullptr, firstPageAddr + pi * 0x10000); } // Local, global, TLS, reloc-only entries. // If TLS entry has a corresponding dynamic relocations, leave it // initialized by zero. Write down adjusted TLS symbol's values otherwise. // To calculate the adjustments use offsets for thread-local storage. // https://www.linux-mips.org/wiki/NPTL - for (const std::pair &P : G.Local16) - Write(P.second, P.first.first, P.first.second); + for (const std::pair &p : g.local16) + write(p.second, p.first.first, p.first.second); // Write VA to the primary GOT only. For secondary GOTs that // will be done by REL32 dynamic relocations. - if (&G == &Gots.front()) - for (const std::pair &P : G.Global) - Write(P.second, P.first, 0); - for (const std::pair &P : G.Relocs) - Write(P.second, P.first, 0); - for (const std::pair &P : G.Tls) - Write(P.second, P.first, P.first->IsPreemptible ? 0 : -0x7000); - for (const std::pair &P : G.DynTlsSymbols) { - if (P.first == nullptr && !Config->Pic) - Write(P.second, nullptr, 1); - else if (P.first && !P.first->IsPreemptible) { + if (&g == &gots.front()) + for (const std::pair &p : g.global) + write(p.second, p.first, 0); + for (const std::pair &p : g.relocs) + write(p.second, p.first, 0); + for (const std::pair &p : g.tls) + write(p.second, p.first, p.first->isPreemptible ? 0 : -0x7000); + for (const std::pair &p : g.dynTlsSymbols) { + if (p.first == nullptr && !config->isPic) + write(p.second, nullptr, 1); + else if (p.first && !p.first->isPreemptible) { // If we are emitting PIC code with relocations we mustn't write // anything to the GOT here. When using Elf_Rel relocations the value // one will be treated as an addend and will cause crashes at runtime - if (!Config->Pic) - Write(P.second, nullptr, 1); - Write(P.second + 1, P.first, -0x8000); + if (!config->isPic) + write(p.second, nullptr, 1); + write(p.second + 1, p.first, -0x8000); } } } @@ -1063,48 +1063,48 @@ // section. I don't know why we have a BSS style type for the section but it is // consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI. GotPltSection::GotPltSection() - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, ".got.plt") { - if (Config->EMachine == EM_PPC) { - Name = ".plt"; - } else if (Config->EMachine == EM_PPC64) { - Type = SHT_NOBITS; - Name = ".plt"; + if (config->emachine == EM_PPC) { + name = ".plt"; + } else if (config->emachine == EM_PPC64) { + type = SHT_NOBITS; + name = ".plt"; } } -void GotPltSection::addEntry(Symbol &Sym) { - assert(Sym.PltIndex == Entries.size()); - Entries.push_back(&Sym); +void GotPltSection::addEntry(Symbol &sym) { + assert(sym.pltIndex == entries.size()); + entries.push_back(&sym); } size_t GotPltSection::getSize() const { - return (Target->GotPltHeaderEntriesNum + Entries.size()) * Config->Wordsize; + return (target->gotPltHeaderEntriesNum + entries.size()) * config->wordsize; } -void GotPltSection::writeTo(uint8_t *Buf) { - Target->writeGotPltHeader(Buf); - Buf += Target->GotPltHeaderEntriesNum * Config->Wordsize; - for (const Symbol *B : Entries) { - Target->writeGotPlt(Buf, *B); - Buf += Config->Wordsize; +void GotPltSection::writeTo(uint8_t *buf) { + target->writeGotPltHeader(buf); + buf += target->gotPltHeaderEntriesNum * config->wordsize; + for (const Symbol *b : entries) { + target->writeGotPlt(buf, *b); + buf += config->wordsize; } } bool GotPltSection::isNeeded() const { // We need to emit GOTPLT even if it's empty if there's a relocation relative // to it. - return !Entries.empty() || HasGotPltOffRel; + return !entries.empty() || hasGotPltOffRel; } static StringRef getIgotPltName() { // On ARM the IgotPltSection is part of the GotSection. - if (Config->EMachine == EM_ARM) + if (config->emachine == EM_ARM) return ".got"; // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection // needs to be named the same. - if (Config->EMachine == EM_PPC64) + if (config->emachine == EM_PPC64) return ".plt"; return ".got.plt"; @@ -1114,28 +1114,28 @@ // with the IgotPltSection. IgotPltSection::IgotPltSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, - Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS, - Config->Wordsize, getIgotPltName()) {} + config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS, + config->wordsize, getIgotPltName()) {} -void IgotPltSection::addEntry(Symbol &Sym) { - assert(Sym.PltIndex == Entries.size()); - Entries.push_back(&Sym); +void IgotPltSection::addEntry(Symbol &sym) { + assert(sym.pltIndex == entries.size()); + entries.push_back(&sym); } size_t IgotPltSection::getSize() const { - return Entries.size() * Config->Wordsize; + return entries.size() * config->wordsize; } -void IgotPltSection::writeTo(uint8_t *Buf) { - for (const Symbol *B : Entries) { - Target->writeIgotPlt(Buf, *B); - Buf += Config->Wordsize; +void IgotPltSection::writeTo(uint8_t *buf) { + for (const Symbol *b : entries) { + target->writeIgotPlt(buf, *b); + buf += config->wordsize; } } -StringTableSection::StringTableSection(StringRef Name, bool Dynamic) - : SyntheticSection(Dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, Name), - Dynamic(Dynamic) { +StringTableSection::StringTableSection(StringRef name, bool dynamic) + : SyntheticSection(dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, name), + dynamic(dynamic) { // ELF string tables start with a NUL byte. addString(""); } @@ -1144,80 +1144,80 @@ // duplicates. It is optional because the name of global symbols are already // uniqued and hashing them again has a big cost for a small value: uniquing // them with some other string that happens to be the same. -unsigned StringTableSection::addString(StringRef S, bool HashIt) { - if (HashIt) { - auto R = StringMap.insert(std::make_pair(S, this->Size)); - if (!R.second) - return R.first->second; - } - unsigned Ret = this->Size; - this->Size = this->Size + S.size() + 1; - Strings.push_back(S); - return Ret; -} - -void StringTableSection::writeTo(uint8_t *Buf) { - for (StringRef S : Strings) { - memcpy(Buf, S.data(), S.size()); - Buf[S.size()] = '\0'; - Buf += S.size() + 1; +unsigned StringTableSection::addString(StringRef s, bool hashIt) { + if (hashIt) { + auto r = stringMap.insert(std::make_pair(s, this->size)); + if (!r.second) + return r.first->second; + } + unsigned ret = this->size; + this->size = this->size + s.size() + 1; + strings.push_back(s); + return ret; +} + +void StringTableSection::writeTo(uint8_t *buf) { + for (StringRef s : strings) { + memcpy(buf, s.data(), s.size()); + buf[s.size()] = '\0'; + buf += s.size() + 1; } } // Returns the number of version definition entries. Because the first entry // is for the version definition itself, it is the number of versioned symbols // plus one. Note that we don't support multiple versions yet. -static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } +static unsigned getVerDefNum() { return config->versionDefinitions.size() + 1; } template DynamicSection::DynamicSection() - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, Config->Wordsize, + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, config->wordsize, ".dynamic") { - this->Entsize = ELFT::Is64Bits ? 16 : 8; + this->entsize = ELFT::Is64Bits ? 16 : 8; // .dynamic section is not writable on MIPS and on Fuchsia OS // which passes -z rodynamic. // See "Special Section" in Chapter 4 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - if (Config->EMachine == EM_MIPS || Config->ZRodynamic) - this->Flags = SHF_ALLOC; + if (config->emachine == EM_MIPS || config->zRodynamic) + this->flags = SHF_ALLOC; } template -void DynamicSection::add(int32_t Tag, std::function Fn) { - Entries.push_back({Tag, Fn}); +void DynamicSection::add(int32_t tag, std::function fn) { + entries.push_back({tag, fn}); } template -void DynamicSection::addInt(int32_t Tag, uint64_t Val) { - Entries.push_back({Tag, [=] { return Val; }}); +void DynamicSection::addInt(int32_t tag, uint64_t val) { + entries.push_back({tag, [=] { return val; }}); } template -void DynamicSection::addInSec(int32_t Tag, InputSection *Sec) { - Entries.push_back({Tag, [=] { return Sec->getVA(0); }}); +void DynamicSection::addInSec(int32_t tag, InputSection *sec) { + entries.push_back({tag, [=] { return sec->getVA(0); }}); } template -void DynamicSection::addInSecRelative(int32_t Tag, InputSection *Sec) { - size_t TagOffset = Entries.size() * Entsize; - Entries.push_back( - {Tag, [=] { return Sec->getVA(0) - (getVA() + TagOffset); }}); +void DynamicSection::addInSecRelative(int32_t tag, InputSection *sec) { + size_t tagOffset = entries.size() * entsize; + entries.push_back( + {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); } template -void DynamicSection::addOutSec(int32_t Tag, OutputSection *Sec) { - Entries.push_back({Tag, [=] { return Sec->Addr; }}); +void DynamicSection::addOutSec(int32_t tag, OutputSection *sec) { + entries.push_back({tag, [=] { return sec->addr; }}); } template -void DynamicSection::addSize(int32_t Tag, OutputSection *Sec) { - Entries.push_back({Tag, [=] { return Sec->Size; }}); +void DynamicSection::addSize(int32_t tag, OutputSection *sec) { + entries.push_back({tag, [=] { return sec->size; }}); } template -void DynamicSection::addSym(int32_t Tag, Symbol *Sym) { - Entries.push_back({Tag, [=] { return Sym->getVA(); }}); +void DynamicSection::addSym(int32_t tag, Symbol *sym) { + entries.push_back({tag, [=] { return sym->getVA(); }}); } // A Linker script may assign the RELA relocation sections to the same @@ -1225,74 +1225,74 @@ // Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to // overlap with the [DT_RELA, DT_RELA + DT_RELASZ). static uint64_t addPltRelSz() { - size_t Size = In.RelaPlt->getSize(); - if (In.RelaIplt->getParent() == In.RelaPlt->getParent() && - In.RelaIplt->Name == In.RelaPlt->Name) - Size += In.RelaIplt->getSize(); - return Size; + size_t size = in.relaPlt->getSize(); + if (in.relaIplt->getParent() == in.relaPlt->getParent() && + in.relaIplt->name == in.relaPlt->name) + size += in.relaIplt->getSize(); + return size; } // Add remaining entries to complete .dynamic contents. template void DynamicSection::finalizeContents() { - elf::Partition &Part = getPartition(); - bool IsMain = Part.Name.empty(); + elf::Partition &part = getPartition(); + bool isMain = part.name.empty(); - for (StringRef S : Config->FilterList) - addInt(DT_FILTER, Part.DynStrTab->addString(S)); - for (StringRef S : Config->AuxiliaryList) - addInt(DT_AUXILIARY, Part.DynStrTab->addString(S)); - - if (!Config->Rpath.empty()) - addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, - Part.DynStrTab->addString(Config->Rpath)); - - for (SharedFile *File : SharedFiles) - if (File->IsNeeded) - addInt(DT_NEEDED, Part.DynStrTab->addString(File->SoName)); - - if (IsMain) { - if (!Config->SoName.empty()) - addInt(DT_SONAME, Part.DynStrTab->addString(Config->SoName)); + for (StringRef s : config->filterList) + addInt(DT_FILTER, part.dynStrTab->addString(s)); + for (StringRef s : config->auxiliaryList) + addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); + + if (!config->rpath.empty()) + addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, + part.dynStrTab->addString(config->rpath)); + + for (SharedFile *file : sharedFiles) + if (file->isNeeded) + addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); + + if (isMain) { + if (!config->soName.empty()) + addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); } else { - if (!Config->SoName.empty()) - addInt(DT_NEEDED, Part.DynStrTab->addString(Config->SoName)); - addInt(DT_SONAME, Part.DynStrTab->addString(Part.Name)); + if (!config->soName.empty()) + addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); + addInt(DT_SONAME, part.dynStrTab->addString(part.name)); } // Set DT_FLAGS and DT_FLAGS_1. - uint32_t DtFlags = 0; - uint32_t DtFlags1 = 0; - if (Config->Bsymbolic) - DtFlags |= DF_SYMBOLIC; - if (Config->ZGlobal) - DtFlags1 |= DF_1_GLOBAL; - if (Config->ZInitfirst) - DtFlags1 |= DF_1_INITFIRST; - if (Config->ZInterpose) - DtFlags1 |= DF_1_INTERPOSE; - if (Config->ZNodefaultlib) - DtFlags1 |= DF_1_NODEFLIB; - if (Config->ZNodelete) - DtFlags1 |= DF_1_NODELETE; - if (Config->ZNodlopen) - DtFlags1 |= DF_1_NOOPEN; - if (Config->ZNow) { - DtFlags |= DF_BIND_NOW; - DtFlags1 |= DF_1_NOW; - } - if (Config->ZOrigin) { - DtFlags |= DF_ORIGIN; - DtFlags1 |= DF_1_ORIGIN; - } - if (!Config->ZText) - DtFlags |= DF_TEXTREL; - if (Config->HasStaticTlsModel) - DtFlags |= DF_STATIC_TLS; - - if (DtFlags) - addInt(DT_FLAGS, DtFlags); - if (DtFlags1) - addInt(DT_FLAGS_1, DtFlags1); + uint32_t dtFlags = 0; + uint32_t dtFlags1 = 0; + if (config->bsymbolic) + dtFlags |= DF_SYMBOLIC; + if (config->zGlobal) + dtFlags1 |= DF_1_GLOBAL; + if (config->zInitfirst) + dtFlags1 |= DF_1_INITFIRST; + if (config->zInterpose) + dtFlags1 |= DF_1_INTERPOSE; + if (config->zNodefaultlib) + dtFlags1 |= DF_1_NODEFLIB; + if (config->zNodelete) + dtFlags1 |= DF_1_NODELETE; + if (config->zNodlopen) + dtFlags1 |= DF_1_NOOPEN; + if (config->zNow) { + dtFlags |= DF_BIND_NOW; + dtFlags1 |= DF_1_NOW; + } + if (config->zOrigin) { + dtFlags |= DF_ORIGIN; + dtFlags1 |= DF_1_ORIGIN; + } + if (!config->zText) + dtFlags |= DF_TEXTREL; + if (config->hasStaticTlsModel) + dtFlags |= DF_STATIC_TLS; + + if (dtFlags) + addInt(DT_FLAGS, dtFlags); + if (dtFlags1) + addInt(DT_FLAGS_1, dtFlags1); // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We // need it for each process, so we don't write it for DSOs. The loader writes @@ -1302,35 +1302,35 @@ // systems (currently only Fuchsia OS) provide other means to give the // debugger this information. Such systems may choose make .dynamic read-only. // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. - if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic) + if (!config->shared && !config->relocatable && !config->zRodynamic) addInt(DT_DEBUG, 0); - if (OutputSection *Sec = Part.DynStrTab->getParent()) - this->Link = Sec->SectionIndex; + if (OutputSection *sec = part.dynStrTab->getParent()) + this->link = sec->sectionIndex; - if (Part.RelaDyn->isNeeded()) { - addInSec(Part.RelaDyn->DynamicTag, Part.RelaDyn); - addSize(Part.RelaDyn->SizeDynamicTag, Part.RelaDyn->getParent()); - - bool IsRela = Config->IsRela; - addInt(IsRela ? DT_RELAENT : DT_RELENT, - IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); + if (part.relaDyn->isNeeded()) { + addInSec(part.relaDyn->dynamicTag, part.relaDyn); + addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); + + bool isRela = config->isRela; + addInt(isRela ? DT_RELAENT : DT_RELENT, + isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); // MIPS dynamic loader does not support RELCOUNT tag. // The problem is in the tight relation between dynamic // relocations and GOT. So do not emit this tag on MIPS. - if (Config->EMachine != EM_MIPS) { - size_t NumRelativeRels = Part.RelaDyn->getRelativeRelocCount(); - if (Config->ZCombreloc && NumRelativeRels) - addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); + if (config->emachine != EM_MIPS) { + size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); + if (config->zCombreloc && numRelativeRels) + addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT, numRelativeRels); } } - if (Part.RelrDyn && !Part.RelrDyn->Relocs.empty()) { - addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, - Part.RelrDyn); - addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, - Part.RelrDyn->getParent()); - addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, + if (part.relrDyn && !part.relrDyn->relocs.empty()) { + addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, + part.relrDyn); + addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, + part.relrDyn->getParent()); + addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, sizeof(Elf_Relr)); } // .rel[a].plt section usually consists of two parts, containing plt and @@ -1339,250 +1339,250 @@ // as RelaIplt have. And we still want to emit proper dynamic tags for that // case, so here we always use RelaPlt as marker for the begining of // .rel[a].plt section. - if (IsMain && (In.RelaPlt->isNeeded() || In.RelaIplt->isNeeded())) { - addInSec(DT_JMPREL, In.RelaPlt); - Entries.push_back({DT_PLTRELSZ, addPltRelSz}); - switch (Config->EMachine) { + if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded())) { + addInSec(DT_JMPREL, in.relaPlt); + entries.push_back({DT_PLTRELSZ, addPltRelSz}); + switch (config->emachine) { case EM_MIPS: - addInSec(DT_MIPS_PLTGOT, In.GotPlt); + addInSec(DT_MIPS_PLTGOT, in.gotPlt); break; case EM_SPARCV9: - addInSec(DT_PLTGOT, In.Plt); + addInSec(DT_PLTGOT, in.plt); break; default: - addInSec(DT_PLTGOT, In.GotPlt); + addInSec(DT_PLTGOT, in.gotPlt); break; } - addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL); + addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL); } - if (Config->EMachine == EM_AARCH64) { - if (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) + if (config->emachine == EM_AARCH64) { + if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) addInt(DT_AARCH64_BTI_PLT, 0); - if (Config->AndFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) + if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) addInt(DT_AARCH64_PAC_PLT, 0); } - addInSec(DT_SYMTAB, Part.DynSymTab); + addInSec(DT_SYMTAB, part.dynSymTab); addInt(DT_SYMENT, sizeof(Elf_Sym)); - addInSec(DT_STRTAB, Part.DynStrTab); - addInt(DT_STRSZ, Part.DynStrTab->getSize()); - if (!Config->ZText) + addInSec(DT_STRTAB, part.dynStrTab); + addInt(DT_STRSZ, part.dynStrTab->getSize()); + if (!config->zText) addInt(DT_TEXTREL, 0); - if (Part.GnuHashTab) - addInSec(DT_GNU_HASH, Part.GnuHashTab); - if (Part.HashTab) - addInSec(DT_HASH, Part.HashTab); - - if (IsMain) { - if (Out::PreinitArray) { - addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray); - addSize(DT_PREINIT_ARRAYSZ, Out::PreinitArray); - } - if (Out::InitArray) { - addOutSec(DT_INIT_ARRAY, Out::InitArray); - addSize(DT_INIT_ARRAYSZ, Out::InitArray); - } - if (Out::FiniArray) { - addOutSec(DT_FINI_ARRAY, Out::FiniArray); - addSize(DT_FINI_ARRAYSZ, Out::FiniArray); - } - - if (Symbol *B = Symtab->find(Config->Init)) - if (B->isDefined()) - addSym(DT_INIT, B); - if (Symbol *B = Symtab->find(Config->Fini)) - if (B->isDefined()) - addSym(DT_FINI, B); - } - - bool HasVerNeed = SharedFile::VernauxNum != 0; - if (HasVerNeed || Part.VerDef) - addInSec(DT_VERSYM, Part.VerSym); - if (Part.VerDef) { - addInSec(DT_VERDEF, Part.VerDef); + if (part.gnuHashTab) + addInSec(DT_GNU_HASH, part.gnuHashTab); + if (part.hashTab) + addInSec(DT_HASH, part.hashTab); + + if (isMain) { + if (Out::preinitArray) { + addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); + addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); + } + if (Out::initArray) { + addOutSec(DT_INIT_ARRAY, Out::initArray); + addSize(DT_INIT_ARRAYSZ, Out::initArray); + } + if (Out::finiArray) { + addOutSec(DT_FINI_ARRAY, Out::finiArray); + addSize(DT_FINI_ARRAYSZ, Out::finiArray); + } + + if (Symbol *b = symtab->find(config->init)) + if (b->isDefined()) + addSym(DT_INIT, b); + if (Symbol *b = symtab->find(config->fini)) + if (b->isDefined()) + addSym(DT_FINI, b); + } + + bool hasVerNeed = SharedFile::vernauxNum != 0; + if (hasVerNeed || part.verDef) + addInSec(DT_VERSYM, part.verSym); + if (part.verDef) { + addInSec(DT_VERDEF, part.verDef); addInt(DT_VERDEFNUM, getVerDefNum()); } - if (HasVerNeed) { - addInSec(DT_VERNEED, Part.VerNeed); - unsigned NeedNum = 0; - for (SharedFile *F : SharedFiles) - if (!F->Vernauxs.empty()) - ++NeedNum; - addInt(DT_VERNEEDNUM, NeedNum); + if (hasVerNeed) { + addInSec(DT_VERNEED, part.verNeed); + unsigned needNum = 0; + for (SharedFile *f : sharedFiles) + if (!f->vernauxs.empty()) + ++needNum; + addInt(DT_VERNEEDNUM, needNum); } - if (Config->EMachine == EM_MIPS) { + if (config->emachine == EM_MIPS) { addInt(DT_MIPS_RLD_VERSION, 1); addInt(DT_MIPS_FLAGS, RHF_NOTPOT); - addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase()); - addInt(DT_MIPS_SYMTABNO, Part.DynSymTab->getNumSymbols()); + addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); + addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); - add(DT_MIPS_LOCAL_GOTNO, [] { return In.MipsGot->getLocalEntriesNum(); }); + add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); - if (const Symbol *B = In.MipsGot->getFirstGlobalEntry()) - addInt(DT_MIPS_GOTSYM, B->DynsymIndex); + if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) + addInt(DT_MIPS_GOTSYM, b->dynsymIndex); else - addInt(DT_MIPS_GOTSYM, Part.DynSymTab->getNumSymbols()); - addInSec(DT_PLTGOT, In.MipsGot); - if (In.MipsRldMap) { - if (!Config->Pie) - addInSec(DT_MIPS_RLD_MAP, In.MipsRldMap); + addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); + addInSec(DT_PLTGOT, in.mipsGot); + if (in.mipsRldMap) { + if (!config->pie) + addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); // Store the offset to the .rld_map section // relative to the address of the tag. - addInSecRelative(DT_MIPS_RLD_MAP_REL, In.MipsRldMap); + addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); } } // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, // glibc assumes the old-style BSS PLT layout which we don't support. - if (Config->EMachine == EM_PPC) - add(DT_PPC_GOT, [] { return In.Got->getVA(); }); + if (config->emachine == EM_PPC) + add(DT_PPC_GOT, [] { return in.got->getVA(); }); // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. - if (Config->EMachine == EM_PPC64 && In.Plt->isNeeded()) { + if (config->emachine == EM_PPC64 && in.plt->isNeeded()) { // The Glink tag points to 32 bytes before the first lazy symbol resolution // stub, which starts directly after the header. - Entries.push_back({DT_PPC64_GLINK, [=] { - unsigned Offset = Target->PltHeaderSize - 32; - return In.Plt->getVA(0) + Offset; + entries.push_back({DT_PPC64_GLINK, [=] { + unsigned offset = target->pltHeaderSize - 32; + return in.plt->getVA(0) + offset; }}); } addInt(DT_NULL, 0); - getParent()->Link = this->Link; - this->Size = Entries.size() * this->Entsize; + getParent()->link = this->link; + this->size = entries.size() * this->entsize; } -template void DynamicSection::writeTo(uint8_t *Buf) { - auto *P = reinterpret_cast(Buf); +template void DynamicSection::writeTo(uint8_t *buf) { + auto *p = reinterpret_cast(buf); - for (std::pair> &KV : Entries) { - P->d_tag = KV.first; - P->d_un.d_val = KV.second(); - ++P; + for (std::pair> &kv : entries) { + p->d_tag = kv.first; + p->d_un.d_val = kv.second(); + ++p; } } uint64_t DynamicReloc::getOffset() const { - return InputSec->getVA(OffsetInSec); + return inputSec->getVA(offsetInSec); } int64_t DynamicReloc::computeAddend() const { - if (UseSymVA) - return Sym->getVA(Addend); - if (!OutputSec) - return Addend; + if (useSymVA) + return sym->getVA(addend); + if (!outputSec) + return addend; // See the comment in the DynamicReloc ctor. - return getMipsPageAddr(OutputSec->Addr) + Addend; + return getMipsPageAddr(outputSec->addr) + addend; } -uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *SymTab) const { - if (Sym && !UseSymVA) - return SymTab->getSymbolIndex(Sym); +uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const { + if (sym && !useSymVA) + return symTab->getSymbolIndex(sym); return 0; } -RelocationBaseSection::RelocationBaseSection(StringRef Name, uint32_t Type, - int32_t DynamicTag, - int32_t SizeDynamicTag) - : SyntheticSection(SHF_ALLOC, Type, Config->Wordsize, Name), - DynamicTag(DynamicTag), SizeDynamicTag(SizeDynamicTag) {} - -void RelocationBaseSection::addReloc(RelType DynType, InputSectionBase *IS, - uint64_t OffsetInSec, Symbol *Sym) { - addReloc({DynType, IS, OffsetInSec, false, Sym, 0}); -} - -void RelocationBaseSection::addReloc(RelType DynType, - InputSectionBase *InputSec, - uint64_t OffsetInSec, Symbol *Sym, - int64_t Addend, RelExpr Expr, - RelType Type) { +RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, + int32_t dynamicTag, + int32_t sizeDynamicTag) + : SyntheticSection(SHF_ALLOC, type, config->wordsize, name), + dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {} + +void RelocationBaseSection::addReloc(RelType dynType, InputSectionBase *isec, + uint64_t offsetInSec, Symbol *sym) { + addReloc({dynType, isec, offsetInSec, false, sym, 0}); +} + +void RelocationBaseSection::addReloc(RelType dynType, + InputSectionBase *inputSec, + uint64_t offsetInSec, Symbol *sym, + int64_t addend, RelExpr expr, + RelType type) { // Write the addends to the relocated address if required. We skip // it if the written value would be zero. - if (Config->WriteAddends && (Expr != R_ADDEND || Addend != 0)) - InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym}); - addReloc({DynType, InputSec, OffsetInSec, Expr != R_ADDEND, Sym, Addend}); + if (config->writeAddends && (expr != R_ADDEND || addend != 0)) + inputSec->relocations.push_back({expr, type, offsetInSec, addend, sym}); + addReloc({dynType, inputSec, offsetInSec, expr != R_ADDEND, sym, addend}); } -void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) { - if (Reloc.Type == Target->RelativeRel) - ++NumRelativeRelocs; - Relocs.push_back(Reloc); +void RelocationBaseSection::addReloc(const DynamicReloc &reloc) { + if (reloc.type == target->relativeRel) + ++numRelativeRelocs; + relocs.push_back(reloc); } void RelocationBaseSection::finalizeContents() { - SymbolTableBaseSection *SymTab = getPartition().DynSymTab; + SymbolTableBaseSection *symTab = getPartition().dynSymTab; // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that // case. - if (SymTab && SymTab->getParent()) - getParent()->Link = SymTab->getParent()->SectionIndex; + if (symTab && symTab->getParent()) + getParent()->link = symTab->getParent()->sectionIndex; else - getParent()->Link = 0; + getParent()->link = 0; - if (In.RelaPlt == this) - getParent()->Info = In.GotPlt->getParent()->SectionIndex; - if (In.RelaIplt == this) - getParent()->Info = In.IgotPlt->getParent()->SectionIndex; + if (in.relaPlt == this) + getParent()->info = in.gotPlt->getParent()->sectionIndex; + if (in.relaIplt == this) + getParent()->info = in.igotPlt->getParent()->sectionIndex; } RelrBaseSection::RelrBaseSection() : SyntheticSection(SHF_ALLOC, - Config->UseAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, - Config->Wordsize, ".relr.dyn") {} + config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, + config->wordsize, ".relr.dyn") {} template -static void encodeDynamicReloc(SymbolTableBaseSection *SymTab, - typename ELFT::Rela *P, - const DynamicReloc &Rel) { - if (Config->IsRela) - P->r_addend = Rel.computeAddend(); - P->r_offset = Rel.getOffset(); - P->setSymbolAndType(Rel.getSymIndex(SymTab), Rel.Type, Config->IsMips64EL); +static void encodeDynamicReloc(SymbolTableBaseSection *symTab, + typename ELFT::Rela *p, + const DynamicReloc &rel) { + if (config->isRela) + p->r_addend = rel.computeAddend(); + p->r_offset = rel.getOffset(); + p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); } template -RelocationSection::RelocationSection(StringRef Name, bool Sort) - : RelocationBaseSection(Name, Config->IsRela ? SHT_RELA : SHT_REL, - Config->IsRela ? DT_RELA : DT_REL, - Config->IsRela ? DT_RELASZ : DT_RELSZ), - Sort(Sort) { - this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); +RelocationSection::RelocationSection(StringRef name, bool sort) + : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, + config->isRela ? DT_RELA : DT_REL, + config->isRela ? DT_RELASZ : DT_RELSZ), + sort(sort) { + this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } -template void RelocationSection::writeTo(uint8_t *Buf) { - SymbolTableBaseSection *SymTab = getPartition().DynSymTab; +template void RelocationSection::writeTo(uint8_t *buf) { + SymbolTableBaseSection *symTab = getPartition().dynSymTab; // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset // is to make results easier to read. - if (Sort) + if (sort) llvm::stable_sort( - Relocs, [&](const DynamicReloc &A, const DynamicReloc &B) { - return std::make_tuple(A.Type != Target->RelativeRel, - A.getSymIndex(SymTab), A.getOffset()) < - std::make_tuple(B.Type != Target->RelativeRel, - B.getSymIndex(SymTab), B.getOffset()); + relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { + return std::make_tuple(a.type != target->relativeRel, + a.getSymIndex(symTab), a.getOffset()) < + std::make_tuple(b.type != target->relativeRel, + b.getSymIndex(symTab), b.getOffset()); }); - for (const DynamicReloc &Rel : Relocs) { - encodeDynamicReloc(SymTab, reinterpret_cast(Buf), Rel); - Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); + for (const DynamicReloc &rel : relocs) { + encodeDynamicReloc(symTab, reinterpret_cast(buf), rel); + buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } } template AndroidPackedRelocationSection::AndroidPackedRelocationSection( - StringRef Name) + StringRef name) : RelocationBaseSection( - Name, Config->IsRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, - Config->IsRela ? DT_ANDROID_RELA : DT_ANDROID_REL, - Config->IsRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { - this->Entsize = 1; + name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, + config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL, + config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { + this->entsize = 1; } template @@ -1632,32 +1632,32 @@ // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for // this relocation. - size_t OldSize = RelocData.size(); + size_t oldSize = relocData.size(); - RelocData = {'A', 'P', 'S', '2'}; - raw_svector_ostream OS(RelocData); - auto Add = [&](int64_t V) { encodeSLEB128(V, OS); }; + relocData = {'A', 'P', 'S', '2'}; + raw_svector_ostream os(relocData); + auto add = [&](int64_t v) { encodeSLEB128(v, os); }; // The format header includes the number of relocations and the initial // offset (we set this to zero because the first relocation group will // perform the initial adjustment). - Add(Relocs.size()); - Add(0); + add(relocs.size()); + add(0); - std::vector Relatives, NonRelatives; + std::vector relatives, nonRelatives; - for (const DynamicReloc &Rel : Relocs) { - Elf_Rela R; - encodeDynamicReloc(getPartition().DynSymTab, &R, Rel); + for (const DynamicReloc &rel : relocs) { + Elf_Rela r; + encodeDynamicReloc(getPartition().dynSymTab, &r, rel); - if (R.getType(Config->IsMips64EL) == Target->RelativeRel) - Relatives.push_back(R); + if (r.getType(config->isMips64EL) == target->relativeRel) + relatives.push_back(r); else - NonRelatives.push_back(R); + nonRelatives.push_back(r); } - llvm::sort(Relatives, [](const Elf_Rel &A, const Elf_Rel &B) { - return A.r_offset < B.r_offset; + llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { + return a.r_offset < b.r_offset; }); // Try to find groups of relative relocations which are spaced one word @@ -1666,108 +1666,108 @@ // encoding, but each group will cost 7 bytes in addition to the offset from // the previous group, so it is only profitable to do this for groups of // size 8 or larger. - std::vector UngroupedRelatives; - std::vector> RelativeGroups; - for (auto I = Relatives.begin(), E = Relatives.end(); I != E;) { - std::vector Group; + std::vector ungroupedRelatives; + std::vector> relativeGroups; + for (auto i = relatives.begin(), e = relatives.end(); i != e;) { + std::vector group; do { - Group.push_back(*I++); - } while (I != E && (I - 1)->r_offset + Config->Wordsize == I->r_offset); + group.push_back(*i++); + } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset); - if (Group.size() < 8) - UngroupedRelatives.insert(UngroupedRelatives.end(), Group.begin(), - Group.end()); + if (group.size() < 8) + ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(), + group.end()); else - RelativeGroups.emplace_back(std::move(Group)); + relativeGroups.emplace_back(std::move(group)); } - unsigned HasAddendIfRela = - Config->IsRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0; + unsigned hasAddendIfRela = + config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0; - uint64_t Offset = 0; - uint64_t Addend = 0; + uint64_t offset = 0; + uint64_t addend = 0; // Emit the run-length encoding for the groups of adjacent relative // relocations. Each group is represented using two groups in the packed // format. The first is used to set the current offset to the start of the // group (and also encodes the first relocation), and the second encodes the // remaining relocations. - for (std::vector &G : RelativeGroups) { + for (std::vector &g : relativeGroups) { // The first relocation in the group. - Add(1); - Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | - RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); - Add(G[0].r_offset - Offset); - Add(Target->RelativeRel); - if (Config->IsRela) { - Add(G[0].r_addend - Addend); - Addend = G[0].r_addend; + add(1); + add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | + RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); + add(g[0].r_offset - offset); + add(target->relativeRel); + if (config->isRela) { + add(g[0].r_addend - addend); + addend = g[0].r_addend; } // The remaining relocations. - Add(G.size() - 1); - Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | - RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); - Add(Config->Wordsize); - Add(Target->RelativeRel); - if (Config->IsRela) { - for (auto I = G.begin() + 1, E = G.end(); I != E; ++I) { - Add(I->r_addend - Addend); - Addend = I->r_addend; + add(g.size() - 1); + add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | + RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); + add(config->wordsize); + add(target->relativeRel); + if (config->isRela) { + for (auto i = g.begin() + 1, e = g.end(); i != e; ++i) { + add(i->r_addend - addend); + addend = i->r_addend; } } - Offset = G.back().r_offset; + offset = g.back().r_offset; } // Now the ungrouped relatives. - if (!UngroupedRelatives.empty()) { - Add(UngroupedRelatives.size()); - Add(RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela); - Add(Target->RelativeRel); - for (Elf_Rela &R : UngroupedRelatives) { - Add(R.r_offset - Offset); - Offset = R.r_offset; - if (Config->IsRela) { - Add(R.r_addend - Addend); - Addend = R.r_addend; + if (!ungroupedRelatives.empty()) { + add(ungroupedRelatives.size()); + add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); + add(target->relativeRel); + for (Elf_Rela &r : ungroupedRelatives) { + add(r.r_offset - offset); + offset = r.r_offset; + if (config->isRela) { + add(r.r_addend - addend); + addend = r.r_addend; } } } // Finally the non-relative relocations. - llvm::sort(NonRelatives, [](const Elf_Rela &A, const Elf_Rela &B) { - return A.r_offset < B.r_offset; + llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { + return a.r_offset < b.r_offset; }); - if (!NonRelatives.empty()) { - Add(NonRelatives.size()); - Add(HasAddendIfRela); - for (Elf_Rela &R : NonRelatives) { - Add(R.r_offset - Offset); - Offset = R.r_offset; - Add(R.r_info); - if (Config->IsRela) { - Add(R.r_addend - Addend); - Addend = R.r_addend; + if (!nonRelatives.empty()) { + add(nonRelatives.size()); + add(hasAddendIfRela); + for (Elf_Rela &r : nonRelatives) { + add(r.r_offset - offset); + offset = r.r_offset; + add(r.r_info); + if (config->isRela) { + add(r.r_addend - addend); + addend = r.r_addend; } } } // Don't allow the section to shrink; otherwise the size of the section can // oscillate infinitely. - if (RelocData.size() < OldSize) - RelocData.append(OldSize - RelocData.size(), 0); + if (relocData.size() < oldSize) + relocData.append(oldSize - relocData.size(), 0); // Returns whether the section size changed. We need to keep recomputing both // section layout and the contents of this section until the size converges // because changing this section's size can affect section layout, which in // turn can affect the sizes of the LEB-encoded integers stored in this // section. - return RelocData.size() != OldSize; + return relocData.size() != oldSize; } template RelrSection::RelrSection() { - this->Entsize = Config->Wordsize; + this->entsize = config->wordsize; } template bool RelrSection::updateAllocSize() { @@ -1801,90 +1801,90 @@ // even means address, odd means bitmap. // 2. Just a simple list of addresses is a valid encoding. - size_t OldSize = RelrRelocs.size(); - RelrRelocs.clear(); + size_t oldSize = relrRelocs.size(); + relrRelocs.clear(); // Same as Config->Wordsize but faster because this is a compile-time // constant. - const size_t Wordsize = sizeof(typename ELFT::uint); + const size_t wordsize = sizeof(typename ELFT::uint); // Number of bits to use for the relocation offsets bitmap. // Must be either 63 or 31. - const size_t NBits = Wordsize * 8 - 1; + const size_t nBits = wordsize * 8 - 1; // Get offsets for all relative relocations and sort them. - std::vector Offsets; - for (const RelativeReloc &Rel : Relocs) - Offsets.push_back(Rel.getOffset()); - llvm::sort(Offsets); + std::vector offsets; + for (const RelativeReloc &rel : relocs) + offsets.push_back(rel.getOffset()); + llvm::sort(offsets); // For each leading relocation, find following ones that can be folded // as a bitmap and fold them. - for (size_t I = 0, E = Offsets.size(); I < E;) { + for (size_t i = 0, e = offsets.size(); i < e;) { // Add a leading relocation. - RelrRelocs.push_back(Elf_Relr(Offsets[I])); - uint64_t Base = Offsets[I] + Wordsize; - ++I; + relrRelocs.push_back(Elf_Relr(offsets[i])); + uint64_t base = offsets[i] + wordsize; + ++i; // Find foldable relocations to construct bitmaps. - while (I < E) { - uint64_t Bitmap = 0; + while (i < e) { + uint64_t bitmap = 0; - while (I < E) { - uint64_t Delta = Offsets[I] - Base; + while (i < e) { + uint64_t delta = offsets[i] - base; // If it is too far, it cannot be folded. - if (Delta >= NBits * Wordsize) + if (delta >= nBits * wordsize) break; // If it is not a multiple of wordsize away, it cannot be folded. - if (Delta % Wordsize) + if (delta % wordsize) break; // Fold it. - Bitmap |= 1ULL << (Delta / Wordsize); - ++I; + bitmap |= 1ULL << (delta / wordsize); + ++i; } - if (!Bitmap) + if (!bitmap) break; - RelrRelocs.push_back(Elf_Relr((Bitmap << 1) | 1)); - Base += NBits * Wordsize; + relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1)); + base += nBits * wordsize; } } - return RelrRelocs.size() != OldSize; + return relrRelocs.size() != oldSize; } -SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec) - : SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0, - StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, - Config->Wordsize, - StrTabSec.isDynamic() ? ".dynsym" : ".symtab"), - StrTabSec(StrTabSec) {} +SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &strTabSec) + : SyntheticSection(strTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0, + strTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, + config->wordsize, + strTabSec.isDynamic() ? ".dynsym" : ".symtab"), + strTabSec(strTabSec) {} // Orders symbols according to their positions in the GOT, // in compliance with MIPS ABI rules. // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf -static bool sortMipsSymbols(const SymbolTableEntry &L, - const SymbolTableEntry &R) { +static bool sortMipsSymbols(const SymbolTableEntry &l, + const SymbolTableEntry &r) { // Sort entries related to non-local preemptible symbols by GOT indexes. // All other entries go to the beginning of a dynsym in arbitrary order. - if (L.Sym->isInGot() && R.Sym->isInGot()) - return L.Sym->GotIndex < R.Sym->GotIndex; - if (!L.Sym->isInGot() && !R.Sym->isInGot()) + if (l.sym->isInGot() && r.sym->isInGot()) + return l.sym->gotIndex < r.sym->gotIndex; + if (!l.sym->isInGot() && !r.sym->isInGot()) return false; - return !L.Sym->isInGot(); + return !l.sym->isInGot(); } void SymbolTableBaseSection::finalizeContents() { - if (OutputSection *Sec = StrTabSec.getParent()) - getParent()->Link = Sec->SectionIndex; + if (OutputSection *sec = strTabSec.getParent()) + getParent()->link = sec->sectionIndex; - if (this->Type != SHT_DYNSYM) { + if (this->type != SHT_DYNSYM) { sortSymTabSymbols(); return; } @@ -1894,21 +1894,21 @@ // Section's Info field has the index of the first non-local symbol. // Because the first symbol entry is a null entry, 1 is the first. - getParent()->Info = 1; + getParent()->info = 1; - if (getPartition().GnuHashTab) { + if (getPartition().gnuHashTab) { // NB: It also sorts Symbols to meet the GNU hash table requirements. - getPartition().GnuHashTab->addSymbols(Symbols); - } else if (Config->EMachine == EM_MIPS) { - llvm::stable_sort(Symbols, sortMipsSymbols); + getPartition().gnuHashTab->addSymbols(symbols); + } else if (config->emachine == EM_MIPS) { + llvm::stable_sort(symbols, sortMipsSymbols); } // Only the main partition's dynsym indexes are stored in the symbols // themselves. All other partitions use a lookup table. - if (this == Main->DynSymTab) { - size_t I = 0; - for (const SymbolTableEntry &S : Symbols) - S.Sym->DynsymIndex = ++I; + if (this == mainPart->dynSymTab) { + size_t i = 0; + for (const SymbolTableEntry &s : symbols) + s.sym->dynsymIndex = ++i; } } @@ -1921,150 +1921,150 @@ // coming from. void SymbolTableBaseSection::sortSymTabSymbols() { // Move all local symbols before global symbols. - auto E = std::stable_partition( - Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { - return S.Sym->isLocal() || S.Sym->computeBinding() == STB_LOCAL; + auto e = std::stable_partition( + symbols.begin(), symbols.end(), [](const SymbolTableEntry &s) { + return s.sym->isLocal() || s.sym->computeBinding() == STB_LOCAL; }); - size_t NumLocals = E - Symbols.begin(); - getParent()->Info = NumLocals + 1; + size_t numLocals = e - symbols.begin(); + getParent()->info = numLocals + 1; // We want to group the local symbols by file. For that we rebuild the local // part of the symbols vector. We do not need to care about the STT_FILE // symbols, they are already naturally placed first in each group. That // happens because STT_FILE is always the first symbol in the object and hence // precede all other local symbols we add for a file. - MapVector> Arr; - for (const SymbolTableEntry &S : llvm::make_range(Symbols.begin(), E)) - Arr[S.Sym->File].push_back(S); + MapVector> arr; + for (const SymbolTableEntry &s : llvm::make_range(symbols.begin(), e)) + arr[s.sym->file].push_back(s); - auto I = Symbols.begin(); - for (std::pair> &P : Arr) - for (SymbolTableEntry &Entry : P.second) - *I++ = Entry; + auto i = symbols.begin(); + for (std::pair> &p : arr) + for (SymbolTableEntry &entry : p.second) + *i++ = entry; } -void SymbolTableBaseSection::addSymbol(Symbol *B) { +void SymbolTableBaseSection::addSymbol(Symbol *b) { // Adding a local symbol to a .dynsym is a bug. - assert(this->Type != SHT_DYNSYM || !B->isLocal()); + assert(this->type != SHT_DYNSYM || !b->isLocal()); - bool HashIt = B->isLocal(); - Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)}); + bool hashIt = b->isLocal(); + symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)}); } -size_t SymbolTableBaseSection::getSymbolIndex(Symbol *Sym) { - if (this == Main->DynSymTab) - return Sym->DynsymIndex; +size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) { + if (this == mainPart->dynSymTab) + return sym->dynsymIndex; // Initializes symbol lookup tables lazily. This is used only for -r, // -emit-relocs and dynsyms in partitions other than the main one. - llvm::call_once(OnceFlag, [&] { - SymbolIndexMap.reserve(Symbols.size()); - size_t I = 0; - for (const SymbolTableEntry &E : Symbols) { - if (E.Sym->Type == STT_SECTION) - SectionIndexMap[E.Sym->getOutputSection()] = ++I; + llvm::call_once(onceFlag, [&] { + symbolIndexMap.reserve(symbols.size()); + size_t i = 0; + for (const SymbolTableEntry &e : symbols) { + if (e.sym->type == STT_SECTION) + sectionIndexMap[e.sym->getOutputSection()] = ++i; else - SymbolIndexMap[E.Sym] = ++I; + symbolIndexMap[e.sym] = ++i; } }); // Section symbols are mapped based on their output sections // to maintain their semantics. - if (Sym->Type == STT_SECTION) - return SectionIndexMap.lookup(Sym->getOutputSection()); - return SymbolIndexMap.lookup(Sym); + if (sym->type == STT_SECTION) + return sectionIndexMap.lookup(sym->getOutputSection()); + return symbolIndexMap.lookup(sym); } template -SymbolTableSection::SymbolTableSection(StringTableSection &StrTabSec) - : SymbolTableBaseSection(StrTabSec) { - this->Entsize = sizeof(Elf_Sym); +SymbolTableSection::SymbolTableSection(StringTableSection &strTabSec) + : SymbolTableBaseSection(strTabSec) { + this->entsize = sizeof(Elf_Sym); } -static BssSection *getCommonSec(Symbol *Sym) { - if (!Config->DefineCommon) - if (auto *D = dyn_cast(Sym)) - return dyn_cast_or_null(D->Section); +static BssSection *getCommonSec(Symbol *sym) { + if (!config->defineCommon) + if (auto *d = dyn_cast(sym)) + return dyn_cast_or_null(d->section); return nullptr; } -static uint32_t getSymSectionIndex(Symbol *Sym) { - if (getCommonSec(Sym)) +static uint32_t getSymSectionIndex(Symbol *sym) { + if (getCommonSec(sym)) return SHN_COMMON; - if (!isa(Sym) || Sym->NeedsPltAddr) + if (!isa(sym) || sym->needsPltAddr) return SHN_UNDEF; - if (const OutputSection *OS = Sym->getOutputSection()) - return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX - : OS->SectionIndex; + if (const OutputSection *os = sym->getOutputSection()) + return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX + : os->sectionIndex; return SHN_ABS; } // Write the internal symbol table contents to the output symbol table. -template void SymbolTableSection::writeTo(uint8_t *Buf) { +template void SymbolTableSection::writeTo(uint8_t *buf) { // The first entry is a null entry as per the ELF spec. - memset(Buf, 0, sizeof(Elf_Sym)); - Buf += sizeof(Elf_Sym); + memset(buf, 0, sizeof(Elf_Sym)); + buf += sizeof(Elf_Sym); - auto *ESym = reinterpret_cast(Buf); + auto *eSym = reinterpret_cast(buf); - for (SymbolTableEntry &Ent : Symbols) { - Symbol *Sym = Ent.Sym; - bool IsDefinedHere = Type == SHT_SYMTAB || Sym->Partition == Partition; + for (SymbolTableEntry &ent : symbols) { + Symbol *sym = ent.sym; + bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition; // Set st_info and st_other. - ESym->st_other = 0; - if (Sym->isLocal()) { - ESym->setBindingAndType(STB_LOCAL, Sym->Type); + eSym->st_other = 0; + if (sym->isLocal()) { + eSym->setBindingAndType(STB_LOCAL, sym->type); } else { - ESym->setBindingAndType(Sym->computeBinding(), Sym->Type); - ESym->setVisibility(Sym->Visibility); + eSym->setBindingAndType(sym->computeBinding(), sym->type); + eSym->setVisibility(sym->visibility); } // The 3 most significant bits of st_other are used by OpenPOWER ABI. // See getPPC64GlobalEntryToLocalEntryOffset() for more details. - if (Config->EMachine == EM_PPC64) - ESym->st_other |= Sym->StOther & 0xe0; + if (config->emachine == EM_PPC64) + eSym->st_other |= sym->stOther & 0xe0; - ESym->st_name = Ent.StrTabOffset; - if (IsDefinedHere) - ESym->st_shndx = getSymSectionIndex(Ent.Sym); + eSym->st_name = ent.strTabOffset; + if (isDefinedHere) + eSym->st_shndx = getSymSectionIndex(ent.sym); else - ESym->st_shndx = 0; + eSym->st_shndx = 0; // Copy symbol size if it is a defined symbol. st_size is not significant // for undefined symbols, so whether copying it or not is up to us if that's // the case. We'll leave it as zero because by not setting a value, we can // get the exact same outputs for two sets of input files that differ only // in undefined symbol size in DSOs. - if (ESym->st_shndx == SHN_UNDEF || !IsDefinedHere) - ESym->st_size = 0; + if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere) + eSym->st_size = 0; else - ESym->st_size = Sym->getSize(); + eSym->st_size = sym->getSize(); // st_value is usually an address of a symbol, but that has a // special meaining for uninstantiated common symbols (this can // occur if -r is given). - if (BssSection *CommonSec = getCommonSec(Ent.Sym)) - ESym->st_value = CommonSec->Alignment; - else if (IsDefinedHere) - ESym->st_value = Sym->getVA(); + if (BssSection *commonSec = getCommonSec(ent.sym)) + eSym->st_value = commonSec->alignment; + else if (isDefinedHere) + eSym->st_value = sym->getVA(); else - ESym->st_value = 0; + eSym->st_value = 0; - ++ESym; + ++eSym; } // On MIPS we need to mark symbol which has a PLT entry and requires // pointer equality by STO_MIPS_PLT flag. That is necessary to help // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. // https://sourceware.org/ml/binutils/2008-07/txt00000.txt - if (Config->EMachine == EM_MIPS) { - auto *ESym = reinterpret_cast(Buf); + if (config->emachine == EM_MIPS) { + auto *eSym = reinterpret_cast(buf); - for (SymbolTableEntry &Ent : Symbols) { - Symbol *Sym = Ent.Sym; - if (Sym->isInPlt() && Sym->NeedsPltAddr) - ESym->st_other |= STO_MIPS_PLT; + for (SymbolTableEntry &ent : symbols) { + Symbol *sym = ent.sym; + if (sym->isInPlt() && sym->needsPltAddr) + eSym->st_other |= STO_MIPS_PLT; if (isMicroMips()) { // We already set the less-significant bit for symbols // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT @@ -2073,36 +2073,36 @@ // clear that bit for non-dynamic symbol table, so tools // like `objdump` will be able to deal with a correct // symbol position. - if (Sym->isDefined() && - ((Sym->StOther & STO_MIPS_MICROMIPS) || Sym->NeedsPltAddr)) { - if (!StrTabSec.isDynamic()) - ESym->st_value &= ~1; - ESym->st_other |= STO_MIPS_MICROMIPS; + if (sym->isDefined() && + ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) { + if (!strTabSec.isDynamic()) + eSym->st_value &= ~1; + eSym->st_other |= STO_MIPS_MICROMIPS; } } - if (Config->Relocatable) - if (auto *D = dyn_cast(Sym)) - if (isMipsPIC(D)) - ESym->st_other |= STO_MIPS_PIC; - ++ESym; + if (config->relocatable) + if (auto *d = dyn_cast(sym)) + if (isMipsPIC(d)) + eSym->st_other |= STO_MIPS_PIC; + ++eSym; } } } SymtabShndxSection::SymtabShndxSection() : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndx") { - this->Entsize = 4; + this->entsize = 4; } -void SymtabShndxSection::writeTo(uint8_t *Buf) { +void SymtabShndxSection::writeTo(uint8_t *buf) { // We write an array of 32 bit values, where each value has 1:1 association // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX, // we need to write actual index, otherwise, we must write SHN_UNDEF(0). - Buf += 4; // Ignore .symtab[0] entry. - for (const SymbolTableEntry &Entry : In.SymTab->getSymbols()) { - if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX) - write32(Buf, Entry.Sym->getOutputSection()->SectionIndex); - Buf += 4; + buf += 4; // Ignore .symtab[0] entry. + for (const SymbolTableEntry &entry : in.symTab->getSymbols()) { + if (getSymSectionIndex(entry.sym) == SHN_XINDEX) + write32(buf, entry.sym->getOutputSection()->sectionIndex); + buf += 4; } } @@ -2112,19 +2112,19 @@ // section. Problem is that we reveal the final section indices a bit too // late, and we do not know them here. For simplicity, we just always create // a .symtab_shndx section when the amount of output sections is huge. - size_t Size = 0; - for (BaseCommand *Base : Script->SectionCommands) - if (isa(Base)) - ++Size; - return Size >= SHN_LORESERVE; + size_t size = 0; + for (BaseCommand *base : script->sectionCommands) + if (isa(base)) + ++size; + return size >= SHN_LORESERVE; } void SymtabShndxSection::finalizeContents() { - getParent()->Link = In.SymTab->getParent()->SectionIndex; + getParent()->link = in.symTab->getParent()->sectionIndex; } size_t SymtabShndxSection::getSize() const { - return In.SymTab->getNumSymbols() * 4; + return in.symTab->getNumSymbols() * 4; } // .hash and .gnu.hash sections contain on-disk hash tables that map @@ -2159,45 +2159,45 @@ // about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a // safe bet is to specify -hash-style=both for backward compatibilty. GnuHashTableSection::GnuHashTableSection() - : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, Config->Wordsize, ".gnu.hash") { + : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, config->wordsize, ".gnu.hash") { } void GnuHashTableSection::finalizeContents() { - if (OutputSection *Sec = getPartition().DynSymTab->getParent()) - getParent()->Link = Sec->SectionIndex; + if (OutputSection *sec = getPartition().dynSymTab->getParent()) + getParent()->link = sec->sectionIndex; // Computes bloom filter size in word size. We want to allocate 12 // bits for each symbol. It must be a power of two. - if (Symbols.empty()) { - MaskWords = 1; + if (symbols.empty()) { + maskWords = 1; } else { - uint64_t NumBits = Symbols.size() * 12; - MaskWords = NextPowerOf2(NumBits / (Config->Wordsize * 8)); + uint64_t numBits = symbols.size() * 12; + maskWords = NextPowerOf2(numBits / (config->wordsize * 8)); } - Size = 16; // Header - Size += Config->Wordsize * MaskWords; // Bloom filter - Size += NBuckets * 4; // Hash buckets - Size += Symbols.size() * 4; // Hash values + size = 16; // Header + size += config->wordsize * maskWords; // Bloom filter + size += nBuckets * 4; // Hash buckets + size += symbols.size() * 4; // Hash values } -void GnuHashTableSection::writeTo(uint8_t *Buf) { +void GnuHashTableSection::writeTo(uint8_t *buf) { // The output buffer is not guaranteed to be zero-cleared because we pre- // fill executable sections with trap instructions. This is a precaution // for that case, which happens only when -no-rosegment is given. - memset(Buf, 0, Size); + memset(buf, 0, size); // Write a header. - write32(Buf, NBuckets); - write32(Buf + 4, getPartition().DynSymTab->getNumSymbols() - Symbols.size()); - write32(Buf + 8, MaskWords); - write32(Buf + 12, Shift2); - Buf += 16; + write32(buf, nBuckets); + write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size()); + write32(buf + 8, maskWords); + write32(buf + 12, Shift2); + buf += 16; // Write a bloom filter and a hash table. - writeBloomFilter(Buf); - Buf += Config->Wordsize * MaskWords; - writeHashTable(Buf); + writeBloomFilter(buf); + buf += config->wordsize * maskWords; + writeHashTable(buf); } // This function writes a 2-bit bloom filter. This bloom filter alone @@ -2207,58 +2207,58 @@ // // [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2), // p.9, https://www.akkadia.org/drepper/dsohowto.pdf -void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) { - unsigned C = Config->Is64 ? 64 : 32; - for (const Entry &Sym : Symbols) { +void GnuHashTableSection::writeBloomFilter(uint8_t *buf) { + unsigned c = config->is64 ? 64 : 32; + for (const Entry &sym : symbols) { // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in // the word using bits [0:5] and [26:31]. - size_t I = (Sym.Hash / C) & (MaskWords - 1); - uint64_t Val = readUint(Buf + I * Config->Wordsize); - Val |= uint64_t(1) << (Sym.Hash % C); - Val |= uint64_t(1) << ((Sym.Hash >> Shift2) % C); - writeUint(Buf + I * Config->Wordsize, Val); + size_t i = (sym.hash / c) & (maskWords - 1); + uint64_t val = readUint(buf + i * config->wordsize); + val |= uint64_t(1) << (sym.hash % c); + val |= uint64_t(1) << ((sym.hash >> Shift2) % c); + writeUint(buf + i * config->wordsize, val); } } -void GnuHashTableSection::writeHashTable(uint8_t *Buf) { - uint32_t *Buckets = reinterpret_cast(Buf); - uint32_t OldBucket = -1; - uint32_t *Values = Buckets + NBuckets; - for (auto I = Symbols.begin(), E = Symbols.end(); I != E; ++I) { +void GnuHashTableSection::writeHashTable(uint8_t *buf) { + uint32_t *buckets = reinterpret_cast(buf); + uint32_t oldBucket = -1; + uint32_t *values = buckets + nBuckets; + for (auto i = symbols.begin(), e = symbols.end(); i != e; ++i) { // Write a hash value. It represents a sequence of chains that share the // same hash modulo value. The last element of each chain is terminated by // LSB 1. - uint32_t Hash = I->Hash; - bool IsLastInChain = (I + 1) == E || I->BucketIdx != (I + 1)->BucketIdx; - Hash = IsLastInChain ? Hash | 1 : Hash & ~1; - write32(Values++, Hash); + uint32_t hash = i->hash; + bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx; + hash = isLastInChain ? hash | 1 : hash & ~1; + write32(values++, hash); - if (I->BucketIdx == OldBucket) + if (i->bucketIdx == oldBucket) continue; // Write a hash bucket. Hash buckets contain indices in the following hash // value table. - write32(Buckets + I->BucketIdx, - getPartition().DynSymTab->getSymbolIndex(I->Sym)); - OldBucket = I->BucketIdx; + write32(buckets + i->bucketIdx, + getPartition().dynSymTab->getSymbolIndex(i->sym)); + oldBucket = i->bucketIdx; } } -static uint32_t hashGnu(StringRef Name) { - uint32_t H = 5381; - for (uint8_t C : Name) - H = (H << 5) + H + C; - return H; +static uint32_t hashGnu(StringRef name) { + uint32_t h = 5381; + for (uint8_t c : name) + h = (h << 5) + h + c; + return h; } // Add symbols to this symbol hash table. Note that this function // destructively sort a given vector -- which is needed because // GNU-style hash table places some sorting requirements. -void GnuHashTableSection::addSymbols(std::vector &V) { +void GnuHashTableSection::addSymbols(std::vector &v) { // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce // its type correctly. - std::vector::iterator Mid = - std::stable_partition(V.begin(), V.end(), [&](const SymbolTableEntry &S) { - return !S.Sym->isDefined() || S.Sym->Partition != Partition; + std::vector::iterator mid = + std::stable_partition(v.begin(), v.end(), [&](const SymbolTableEntry &s) { + return !s.sym->isDefined() || s.sym->partition != partition; }); // We chose load factor 4 for the on-disk hash table. For each hash @@ -2270,143 +2270,143 @@ // Android loader as of 2018 doesn't like a .gnu.hash containing such // table. If that's the case, we create a hash table with one unused // dummy slot. - NBuckets = std::max((V.end() - Mid) / 4, 1); + nBuckets = std::max((v.end() - mid) / 4, 1); - if (Mid == V.end()) + if (mid == v.end()) return; - for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) { - Symbol *B = Ent.Sym; - uint32_t Hash = hashGnu(B->getName()); - uint32_t BucketIdx = Hash % NBuckets; - Symbols.push_back({B, Ent.StrTabOffset, Hash, BucketIdx}); + for (SymbolTableEntry &ent : llvm::make_range(mid, v.end())) { + Symbol *b = ent.sym; + uint32_t hash = hashGnu(b->getName()); + uint32_t bucketIdx = hash % nBuckets; + symbols.push_back({b, ent.strTabOffset, hash, bucketIdx}); } - llvm::stable_sort(Symbols, [](const Entry &L, const Entry &R) { - return L.BucketIdx < R.BucketIdx; + llvm::stable_sort(symbols, [](const Entry &l, const Entry &r) { + return l.bucketIdx < r.bucketIdx; }); - V.erase(Mid, V.end()); - for (const Entry &Ent : Symbols) - V.push_back({Ent.Sym, Ent.StrTabOffset}); + v.erase(mid, v.end()); + for (const Entry &ent : symbols) + v.push_back({ent.sym, ent.strTabOffset}); } HashTableSection::HashTableSection() : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") { - this->Entsize = 4; + this->entsize = 4; } void HashTableSection::finalizeContents() { - SymbolTableBaseSection *SymTab = getPartition().DynSymTab; + SymbolTableBaseSection *symTab = getPartition().dynSymTab; - if (OutputSection *Sec = SymTab->getParent()) - getParent()->Link = Sec->SectionIndex; + if (OutputSection *sec = symTab->getParent()) + getParent()->link = sec->sectionIndex; - unsigned NumEntries = 2; // nbucket and nchain. - NumEntries += SymTab->getNumSymbols(); // The chain entries. + unsigned numEntries = 2; // nbucket and nchain. + numEntries += symTab->getNumSymbols(); // The chain entries. // Create as many buckets as there are symbols. - NumEntries += SymTab->getNumSymbols(); - this->Size = NumEntries * 4; + numEntries += symTab->getNumSymbols(); + this->size = numEntries * 4; } -void HashTableSection::writeTo(uint8_t *Buf) { - SymbolTableBaseSection *SymTab = getPartition().DynSymTab; +void HashTableSection::writeTo(uint8_t *buf) { + SymbolTableBaseSection *symTab = getPartition().dynSymTab; // See comment in GnuHashTableSection::writeTo. - memset(Buf, 0, Size); + memset(buf, 0, size); - unsigned NumSymbols = SymTab->getNumSymbols(); + unsigned numSymbols = symTab->getNumSymbols(); - uint32_t *P = reinterpret_cast(Buf); - write32(P++, NumSymbols); // nbucket - write32(P++, NumSymbols); // nchain - - uint32_t *Buckets = P; - uint32_t *Chains = P + NumSymbols; - - for (const SymbolTableEntry &S : SymTab->getSymbols()) { - Symbol *Sym = S.Sym; - StringRef Name = Sym->getName(); - unsigned I = Sym->DynsymIndex; - uint32_t Hash = hashSysV(Name) % NumSymbols; - Chains[I] = Buckets[Hash]; - write32(Buckets + Hash, I); + uint32_t *p = reinterpret_cast(buf); + write32(p++, numSymbols); // nbucket + write32(p++, numSymbols); // nchain + + uint32_t *buckets = p; + uint32_t *chains = p + numSymbols; + + for (const SymbolTableEntry &s : symTab->getSymbols()) { + Symbol *sym = s.sym; + StringRef name = sym->getName(); + unsigned i = sym->dynsymIndex; + uint32_t hash = hashSysV(name) % numSymbols; + chains[i] = buckets[hash]; + write32(buckets + hash, i); } } // On PowerPC64 the lazy symbol resolvers go into the `global linkage table` // in the .glink section, rather then the typical .plt section. -PltSection::PltSection(bool IsIplt) +PltSection::PltSection(bool isIplt) : SyntheticSection( SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, - (Config->EMachine == EM_PPC || Config->EMachine == EM_PPC64) + (config->emachine == EM_PPC || config->emachine == EM_PPC64) ? ".glink" : ".plt"), - HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0), - IsIplt(IsIplt) { + headerSize(!isIplt || config->zRetpolineplt ? target->pltHeaderSize : 0), + isIplt(isIplt) { // The PLT needs to be writable on SPARC as the dynamic linker will // modify the instructions in the PLT entries. - if (Config->EMachine == EM_SPARCV9) - this->Flags |= SHF_WRITE; + if (config->emachine == EM_SPARCV9) + this->flags |= SHF_WRITE; } -void PltSection::writeTo(uint8_t *Buf) { - if (Config->EMachine == EM_PPC) { - writePPC32GlinkSection(Buf, Entries.size()); +void PltSection::writeTo(uint8_t *buf) { + if (config->emachine == EM_PPC) { + writePPC32GlinkSection(buf, entries.size()); return; } // At beginning of PLT or retpoline IPLT, we have code to call the dynamic // linker to resolve dynsyms at runtime. Write such code. - if (HeaderSize) - Target->writePltHeader(Buf); - size_t Off = HeaderSize; + if (headerSize) + target->writePltHeader(buf); + size_t off = headerSize; - RelocationBaseSection *RelSec = IsIplt ? In.RelaIplt : In.RelaPlt; + RelocationBaseSection *relSec = isIplt ? in.relaIplt : in.relaPlt; // The IPlt is immediately after the Plt, account for this in RelOff - size_t PltOff = IsIplt ? In.Plt->getSize() : 0; + size_t pltOff = isIplt ? in.plt->getSize() : 0; - for (size_t I = 0, E = Entries.size(); I != E; ++I) { - const Symbol *B = Entries[I]; - unsigned RelOff = RelSec->Entsize * I + PltOff; - uint64_t Got = B->getGotPltVA(); - uint64_t Plt = this->getVA() + Off; - Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); - Off += Target->PltEntrySize; + for (size_t i = 0, e = entries.size(); i != e; ++i) { + const Symbol *b = entries[i]; + unsigned relOff = relSec->entsize * i + pltOff; + uint64_t got = b->getGotPltVA(); + uint64_t plt = this->getVA() + off; + target->writePlt(buf + off, got, plt, b->pltIndex, relOff); + off += target->pltEntrySize; } } -template void PltSection::addEntry(Symbol &Sym) { - Sym.PltIndex = Entries.size(); - Entries.push_back(&Sym); +template void PltSection::addEntry(Symbol &sym) { + sym.pltIndex = entries.size(); + entries.push_back(&sym); } size_t PltSection::getSize() const { - return HeaderSize + Entries.size() * Target->PltEntrySize; + return headerSize + entries.size() * target->pltEntrySize; } // Some architectures such as additional symbols in the PLT section. For // example ARM uses mapping symbols to aid disassembly void PltSection::addSymbols() { // The PLT may have symbols defined for the Header, the IPLT has no header - if (!IsIplt) - Target->addPltHeaderSymbols(*this); + if (!isIplt) + target->addPltHeaderSymbols(*this); - size_t Off = HeaderSize; - for (size_t I = 0; I < Entries.size(); ++I) { - Target->addPltSymbols(*this, Off); - Off += Target->PltEntrySize; + size_t off = headerSize; + for (size_t i = 0; i < entries.size(); ++i) { + target->addPltSymbols(*this, off); + off += target->pltEntrySize; } } // The string hash function for .gdb_index. -static uint32_t computeGdbHash(StringRef S) { - uint32_t H = 0; - for (uint8_t C : S) - H = H * 67 + toLower(C) - 113; - return H; +static uint32_t computeGdbHash(StringRef s) { + uint32_t h = 0; + for (uint8_t c : s) + h = h * 67 + toLower(c) - 113; + return h; } GdbIndexSection::GdbIndexSection() @@ -2415,287 +2415,287 @@ // Returns the desired size of an on-disk hash table for a .gdb_index section. // There's a tradeoff between size and collision rate. We aim 75% utilization. size_t GdbIndexSection::computeSymtabSize() const { - return std::max(NextPowerOf2(Symbols.size() * 4 / 3), 1024); + return std::max(NextPowerOf2(symbols.size() * 4 / 3), 1024); } // Compute the output section size. void GdbIndexSection::initOutputSize() { - Size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8; + size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8; - for (GdbChunk &Chunk : Chunks) - Size += Chunk.CompilationUnits.size() * 16 + Chunk.AddressAreas.size() * 20; + for (GdbChunk &chunk : chunks) + size += chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20; // Add the constant pool size if exists. - if (!Symbols.empty()) { - GdbSymbol &Sym = Symbols.back(); - Size += Sym.NameOff + Sym.Name.size() + 1; + if (!symbols.empty()) { + GdbSymbol &sym = symbols.back(); + size += sym.nameOff + sym.name.size() + 1; } } static std::vector getDebugInfoSections() { - std::vector Ret; - for (InputSectionBase *S : InputSections) - if (InputSection *IS = dyn_cast(S)) - if (IS->Name == ".debug_info") - Ret.push_back(IS); - return Ret; + std::vector ret; + for (InputSectionBase *s : inputSections) + if (InputSection *isec = dyn_cast(s)) + if (isec->name == ".debug_info") + ret.push_back(isec); + return ret; } -static std::vector readCuList(DWARFContext &Dwarf) { - std::vector Ret; - for (std::unique_ptr &Cu : Dwarf.compile_units()) - Ret.push_back({Cu->getOffset(), Cu->getLength() + 4}); - return Ret; +static std::vector readCuList(DWARFContext &dwarf) { + std::vector ret; + for (std::unique_ptr &cu : dwarf.compile_units()) + ret.push_back({cu->getOffset(), cu->getLength() + 4}); + return ret; } static std::vector -readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) { - std::vector Ret; +readAddressAreas(DWARFContext &dwarf, InputSection *sec) { + std::vector ret; - uint32_t CuIdx = 0; - for (std::unique_ptr &Cu : Dwarf.compile_units()) { - Expected Ranges = Cu->collectAddressRanges(); - if (!Ranges) { - error(toString(Sec) + ": " + toString(Ranges.takeError())); + uint32_t cuIdx = 0; + for (std::unique_ptr &cu : dwarf.compile_units()) { + Expected ranges = cu->collectAddressRanges(); + if (!ranges) { + error(toString(sec) + ": " + toString(ranges.takeError())); return {}; } - ArrayRef Sections = Sec->File->getSections(); - for (DWARFAddressRange &R : *Ranges) { - if (R.SectionIndex == -1ULL) + ArrayRef sections = sec->file->getSections(); + for (DWARFAddressRange &r : *ranges) { + if (r.SectionIndex == -1ULL) continue; - InputSectionBase *S = Sections[R.SectionIndex]; - if (!S || S == &InputSection::Discarded || !S->isLive()) + InputSectionBase *s = sections[r.SectionIndex]; + if (!s || s == &InputSection::discarded || !s->isLive()) continue; // Range list with zero size has no effect. - if (R.LowPC == R.HighPC) + if (r.LowPC == r.HighPC) continue; - auto *IS = cast(S); - uint64_t Offset = IS->getOffsetInFile(); - Ret.push_back({IS, R.LowPC - Offset, R.HighPC - Offset, CuIdx}); + auto *isec = cast(s); + uint64_t offset = isec->getOffsetInFile(); + ret.push_back({isec, r.LowPC - offset, r.HighPC - offset, cuIdx}); } - ++CuIdx; + ++cuIdx; } - return Ret; + return ret; } template static std::vector -readPubNamesAndTypes(const LLDDwarfObj &Obj, - const std::vector &CUs) { - const DWARFSection &PubNames = Obj.getGnuPubNamesSection(); - const DWARFSection &PubTypes = Obj.getGnuPubTypesSection(); - - std::vector Ret; - for (const DWARFSection *Pub : {&PubNames, &PubTypes}) { - DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true); - for (const DWARFDebugPubTable::Set &Set : Table.getData()) { +readPubNamesAndTypes(const LLDDwarfObj &obj, + const std::vector &cUs) { + const DWARFSection &pubNames = obj.getGnuPubNamesSection(); + const DWARFSection &pubTypes = obj.getGnuPubTypesSection(); + + std::vector ret; + for (const DWARFSection *pub : {&pubNames, &pubTypes}) { + DWARFDebugPubTable table(obj, *pub, config->isLE, true); + for (const DWARFDebugPubTable::Set &set : table.getData()) { // The value written into the constant pool is Kind << 24 | CuIndex. As we // don't know how many compilation units precede this object to compute // CuIndex, we compute (Kind << 24 | CuIndexInThisObject) instead, and add // the number of preceding compilation units later. - uint32_t I = - lower_bound(CUs, Set.Offset, - [](GdbIndexSection::CuEntry CU, uint32_t Offset) { - return CU.CuOffset < Offset; + uint32_t i = + lower_bound(cUs, set.Offset, + [](GdbIndexSection::CuEntry cu, uint32_t offset) { + return cu.cuOffset < offset; }) - - CUs.begin(); - for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) - Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)}, - (Ent.Descriptor.toBits() << 24) | I}); + cUs.begin(); + for (const DWARFDebugPubTable::Entry &ent : set.Entries) + ret.push_back({{ent.Name, computeGdbHash(ent.Name)}, + (ent.Descriptor.toBits() << 24) | i}); } } - return Ret; + return ret; } // Create a list of symbols from a given list of symbol names and types // by uniquifying them by name. static std::vector -createSymbols(ArrayRef> NameAttrs, - const std::vector &Chunks) { +createSymbols(ArrayRef> nameAttrs, + const std::vector &chunks) { using GdbSymbol = GdbIndexSection::GdbSymbol; using NameAttrEntry = GdbIndexSection::NameAttrEntry; // For each chunk, compute the number of compilation units preceding it. - uint32_t CuIdx = 0; - std::vector CuIdxs(Chunks.size()); - for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { - CuIdxs[I] = CuIdx; - CuIdx += Chunks[I].CompilationUnits.size(); + uint32_t cuIdx = 0; + std::vector cuIdxs(chunks.size()); + for (uint32_t i = 0, e = chunks.size(); i != e; ++i) { + cuIdxs[i] = cuIdx; + cuIdx += chunks[i].compilationUnits.size(); } // The number of symbols we will handle in this function is of the order // of millions for very large executables, so we use multi-threading to // speed it up. - size_t NumShards = 32; - size_t Concurrency = 1; + size_t numShards = 32; + size_t concurrency = 1; if (ThreadsEnabled) - Concurrency = - std::min(PowerOf2Floor(hardware_concurrency()), NumShards); + concurrency = + std::min(PowerOf2Floor(hardware_concurrency()), numShards); // A sharded map to uniquify symbols by name. - std::vector> Map(NumShards); - size_t Shift = 32 - countTrailingZeros(NumShards); + std::vector> map(numShards); + size_t shift = 32 - countTrailingZeros(numShards); // Instantiate GdbSymbols while uniqufying them by name. - std::vector> Symbols(NumShards); - parallelForEachN(0, Concurrency, [&](size_t ThreadId) { - uint32_t I = 0; - for (ArrayRef Entries : NameAttrs) { - for (const NameAttrEntry &Ent : Entries) { - size_t ShardId = Ent.Name.hash() >> Shift; - if ((ShardId & (Concurrency - 1)) != ThreadId) + std::vector> symbols(numShards); + parallelForEachN(0, concurrency, [&](size_t threadId) { + uint32_t i = 0; + for (ArrayRef entries : nameAttrs) { + for (const NameAttrEntry &ent : entries) { + size_t shardId = ent.name.hash() >> shift; + if ((shardId & (concurrency - 1)) != threadId) continue; - uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I]; - size_t &Idx = Map[ShardId][Ent.Name]; - if (Idx) { - Symbols[ShardId][Idx - 1].CuVector.push_back(V); + uint32_t v = ent.cuIndexAndAttrs + cuIdxs[i]; + size_t &idx = map[shardId][ent.name]; + if (idx) { + symbols[shardId][idx - 1].cuVector.push_back(v); continue; } - Idx = Symbols[ShardId].size() + 1; - Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0}); + idx = symbols[shardId].size() + 1; + symbols[shardId].push_back({ent.name, {v}, 0, 0}); } - ++I; + ++i; } }); - size_t NumSymbols = 0; - for (ArrayRef V : Symbols) - NumSymbols += V.size(); + size_t numSymbols = 0; + for (ArrayRef v : symbols) + numSymbols += v.size(); // The return type is a flattened vector, so we'll copy each vector // contents to Ret. - std::vector Ret; - Ret.reserve(NumSymbols); - for (std::vector &Vec : Symbols) - for (GdbSymbol &Sym : Vec) - Ret.push_back(std::move(Sym)); + std::vector ret; + ret.reserve(numSymbols); + for (std::vector &vec : symbols) + for (GdbSymbol &sym : vec) + ret.push_back(std::move(sym)); // CU vectors and symbol names are adjacent in the output file. // We can compute their offsets in the output file now. - size_t Off = 0; - for (GdbSymbol &Sym : Ret) { - Sym.CuVectorOff = Off; - Off += (Sym.CuVector.size() + 1) * 4; + size_t off = 0; + for (GdbSymbol &sym : ret) { + sym.cuVectorOff = off; + off += (sym.cuVector.size() + 1) * 4; } - for (GdbSymbol &Sym : Ret) { - Sym.NameOff = Off; - Off += Sym.Name.size() + 1; + for (GdbSymbol &sym : ret) { + sym.nameOff = off; + off += sym.name.size() + 1; } - return Ret; + return ret; } // Returns a newly-created .gdb_index section. template GdbIndexSection *GdbIndexSection::create() { - std::vector Sections = getDebugInfoSections(); + std::vector sections = getDebugInfoSections(); // .debug_gnu_pub{names,types} are useless in executables. // They are present in input object files solely for creating // a .gdb_index. So we can remove them from the output. - for (InputSectionBase *S : InputSections) - if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes") - S->markDead(); - - std::vector Chunks(Sections.size()); - std::vector> NameAttrs(Sections.size()); - - parallelForEachN(0, Sections.size(), [&](size_t I) { - ObjFile *File = Sections[I]->getFile(); - DWARFContext Dwarf(make_unique>(File)); - - Chunks[I].Sec = Sections[I]; - Chunks[I].CompilationUnits = readCuList(Dwarf); - Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); - NameAttrs[I] = readPubNamesAndTypes( - static_cast &>(Dwarf.getDWARFObj()), - Chunks[I].CompilationUnits); + for (InputSectionBase *s : inputSections) + if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") + s->markDead(); + + std::vector chunks(sections.size()); + std::vector> nameAttrs(sections.size()); + + parallelForEachN(0, sections.size(), [&](size_t i) { + ObjFile *file = sections[i]->getFile(); + DWARFContext dwarf(make_unique>(file)); + + chunks[i].sec = sections[i]; + chunks[i].compilationUnits = readCuList(dwarf); + chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); + nameAttrs[i] = readPubNamesAndTypes( + static_cast &>(dwarf.getDWARFObj()), + chunks[i].compilationUnits); }); - auto *Ret = make(); - Ret->Chunks = std::move(Chunks); - Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks); - Ret->initOutputSize(); - return Ret; + auto *ret = make(); + ret->chunks = std::move(chunks); + ret->symbols = createSymbols(nameAttrs, ret->chunks); + ret->initOutputSize(); + return ret; } -void GdbIndexSection::writeTo(uint8_t *Buf) { +void GdbIndexSection::writeTo(uint8_t *buf) { // Write the header. - auto *Hdr = reinterpret_cast(Buf); - uint8_t *Start = Buf; - Hdr->Version = 7; - Buf += sizeof(*Hdr); + auto *hdr = reinterpret_cast(buf); + uint8_t *start = buf; + hdr->version = 7; + buf += sizeof(*hdr); // Write the CU list. - Hdr->CuListOff = Buf - Start; - for (GdbChunk &Chunk : Chunks) { - for (CuEntry &Cu : Chunk.CompilationUnits) { - write64le(Buf, Chunk.Sec->OutSecOff + Cu.CuOffset); - write64le(Buf + 8, Cu.CuLength); - Buf += 16; + hdr->cuListOff = buf - start; + for (GdbChunk &chunk : chunks) { + for (CuEntry &cu : chunk.compilationUnits) { + write64le(buf, chunk.sec->outSecOff + cu.cuOffset); + write64le(buf + 8, cu.cuLength); + buf += 16; } } // Write the address area. - Hdr->CuTypesOff = Buf - Start; - Hdr->AddressAreaOff = Buf - Start; - uint32_t CuOff = 0; - for (GdbChunk &Chunk : Chunks) { - for (AddressEntry &E : Chunk.AddressAreas) { - uint64_t BaseAddr = E.Section->getVA(0); - write64le(Buf, BaseAddr + E.LowAddress); - write64le(Buf + 8, BaseAddr + E.HighAddress); - write32le(Buf + 16, E.CuIndex + CuOff); - Buf += 20; + hdr->cuTypesOff = buf - start; + hdr->addressAreaOff = buf - start; + uint32_t cuOff = 0; + for (GdbChunk &chunk : chunks) { + for (AddressEntry &e : chunk.addressAreas) { + uint64_t baseAddr = e.section->getVA(0); + write64le(buf, baseAddr + e.lowAddress); + write64le(buf + 8, baseAddr + e.highAddress); + write32le(buf + 16, e.cuIndex + cuOff); + buf += 20; } - CuOff += Chunk.CompilationUnits.size(); + cuOff += chunk.compilationUnits.size(); } // Write the on-disk open-addressing hash table containing symbols. - Hdr->SymtabOff = Buf - Start; - size_t SymtabSize = computeSymtabSize(); - uint32_t Mask = SymtabSize - 1; + hdr->symtabOff = buf - start; + size_t symtabSize = computeSymtabSize(); + uint32_t mask = symtabSize - 1; - for (GdbSymbol &Sym : Symbols) { - uint32_t H = Sym.Name.hash(); - uint32_t I = H & Mask; - uint32_t Step = ((H * 17) & Mask) | 1; + for (GdbSymbol &sym : symbols) { + uint32_t h = sym.name.hash(); + uint32_t i = h & mask; + uint32_t step = ((h * 17) & mask) | 1; - while (read32le(Buf + I * 8)) - I = (I + Step) & Mask; + while (read32le(buf + i * 8)) + i = (i + step) & mask; - write32le(Buf + I * 8, Sym.NameOff); - write32le(Buf + I * 8 + 4, Sym.CuVectorOff); + write32le(buf + i * 8, sym.nameOff); + write32le(buf + i * 8 + 4, sym.cuVectorOff); } - Buf += SymtabSize * 8; + buf += symtabSize * 8; // Write the string pool. - Hdr->ConstantPoolOff = Buf - Start; - parallelForEach(Symbols, [&](GdbSymbol &Sym) { - memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size()); + hdr->constantPoolOff = buf - start; + parallelForEach(symbols, [&](GdbSymbol &sym) { + memcpy(buf + sym.nameOff, sym.name.data(), sym.name.size()); }); // Write the CU vectors. - for (GdbSymbol &Sym : Symbols) { - write32le(Buf, Sym.CuVector.size()); - Buf += 4; - for (uint32_t Val : Sym.CuVector) { - write32le(Buf, Val); - Buf += 4; + for (GdbSymbol &sym : symbols) { + write32le(buf, sym.cuVector.size()); + buf += 4; + for (uint32_t val : sym.cuVector) { + write32le(buf, val); + buf += 4; } } } -bool GdbIndexSection::isNeeded() const { return !Chunks.empty(); } +bool GdbIndexSection::isNeeded() const { return !chunks.empty(); } EhFrameHeader::EhFrameHeader() : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {} -void EhFrameHeader::writeTo(uint8_t *Buf) { +void EhFrameHeader::writeTo(uint8_t *buf) { // Unlike most sections, the EhFrameHeader section is written while writing // another section, namely EhFrameSection, which calls the write() function // below from its writeTo() function. This is necessary because the contents @@ -2708,34 +2708,34 @@ // the starting PC from where FDEs covers, and the FDE's address. // It is sorted by PC. void EhFrameHeader::write() { - uint8_t *Buf = Out::BufferStart + getParent()->Offset + OutSecOff; + uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; using FdeData = EhFrameSection::FdeData; - std::vector Fdes = getPartition().EhFrame->getFdeData(); + std::vector fdes = getPartition().ehFrame->getFdeData(); - Buf[0] = 1; - Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; - Buf[2] = DW_EH_PE_udata4; - Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; - write32(Buf + 4, - getPartition().EhFrame->getParent()->Addr - this->getVA() - 4); - write32(Buf + 8, Fdes.size()); - Buf += 12; - - for (FdeData &Fde : Fdes) { - write32(Buf, Fde.PcRel); - write32(Buf + 4, Fde.FdeVARel); - Buf += 8; + buf[0] = 1; + buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; + buf[2] = DW_EH_PE_udata4; + buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; + write32(buf + 4, + getPartition().ehFrame->getParent()->addr - this->getVA() - 4); + write32(buf + 8, fdes.size()); + buf += 12; + + for (FdeData &fde : fdes) { + write32(buf, fde.pcRel); + write32(buf + 4, fde.fdeVARel); + buf += 8; } } size_t EhFrameHeader::getSize() const { // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. - return 12 + getPartition().EhFrame->NumFdes * 8; + return 12 + getPartition().ehFrame->numFdes * 8; } bool EhFrameHeader::isNeeded() const { - return isLive() && getPartition().EhFrame->isNeeded(); + return isLive() && getPartition().ehFrame->isNeeded(); } VersionDefinitionSection::VersionDefinitionSection() @@ -2743,56 +2743,56 @@ ".gnu.version_d") {} StringRef VersionDefinitionSection::getFileDefName() { - if (!getPartition().Name.empty()) - return getPartition().Name; - if (!Config->SoName.empty()) - return Config->SoName; - return Config->OutputFile; + if (!getPartition().name.empty()) + return getPartition().name; + if (!config->soName.empty()) + return config->soName; + return config->outputFile; } void VersionDefinitionSection::finalizeContents() { - FileDefNameOff = getPartition().DynStrTab->addString(getFileDefName()); - for (VersionDefinition &V : Config->VersionDefinitions) - VerDefNameOffs.push_back(getPartition().DynStrTab->addString(V.Name)); + fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName()); + for (VersionDefinition &v : config->versionDefinitions) + verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name)); - if (OutputSection *Sec = getPartition().DynStrTab->getParent()) - getParent()->Link = Sec->SectionIndex; + if (OutputSection *sec = getPartition().dynStrTab->getParent()) + getParent()->link = sec->sectionIndex; // sh_info should be set to the number of definitions. This fact is missed in // documentation, but confirmed by binutils community: // https://sourceware.org/ml/binutils/2014-11/msg00355.html - getParent()->Info = getVerDefNum(); + getParent()->info = getVerDefNum(); } -void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index, - StringRef Name, size_t NameOff) { - uint16_t Flags = Index == 1 ? VER_FLG_BASE : 0; +void VersionDefinitionSection::writeOne(uint8_t *buf, uint32_t index, + StringRef name, size_t nameOff) { + uint16_t flags = index == 1 ? VER_FLG_BASE : 0; // Write a verdef. - write16(Buf, 1); // vd_version - write16(Buf + 2, Flags); // vd_flags - write16(Buf + 4, Index); // vd_ndx - write16(Buf + 6, 1); // vd_cnt - write32(Buf + 8, hashSysV(Name)); // vd_hash - write32(Buf + 12, 20); // vd_aux - write32(Buf + 16, 28); // vd_next + write16(buf, 1); // vd_version + write16(buf + 2, flags); // vd_flags + write16(buf + 4, index); // vd_ndx + write16(buf + 6, 1); // vd_cnt + write32(buf + 8, hashSysV(name)); // vd_hash + write32(buf + 12, 20); // vd_aux + write32(buf + 16, 28); // vd_next // Write a veraux. - write32(Buf + 20, NameOff); // vda_name - write32(Buf + 24, 0); // vda_next + write32(buf + 20, nameOff); // vda_name + write32(buf + 24, 0); // vda_next } -void VersionDefinitionSection::writeTo(uint8_t *Buf) { - writeOne(Buf, 1, getFileDefName(), FileDefNameOff); +void VersionDefinitionSection::writeTo(uint8_t *buf) { + writeOne(buf, 1, getFileDefName(), fileDefNameOff); - auto NameOffIt = VerDefNameOffs.begin(); - for (VersionDefinition &V : Config->VersionDefinitions) { - Buf += EntrySize; - writeOne(Buf, V.Id, V.Name, *NameOffIt++); + auto nameOffIt = verDefNameOffs.begin(); + for (VersionDefinition &v : config->versionDefinitions) { + buf += EntrySize; + writeOne(buf, v.id, v.name, *nameOffIt++); } // Need to terminate the last version definition. - write32(Buf + 16, 0); // vd_next + write32(buf + 16, 0); // vd_next } size_t VersionDefinitionSection::getSize() const { @@ -2803,49 +2803,49 @@ VersionTableSection::VersionTableSection() : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t), ".gnu.version") { - this->Entsize = 2; + this->entsize = 2; } void VersionTableSection::finalizeContents() { // At the moment of june 2016 GNU docs does not mention that sh_link field // should be set, but Sun docs do. Also readelf relies on this field. - getParent()->Link = getPartition().DynSymTab->getParent()->SectionIndex; + getParent()->link = getPartition().dynSymTab->getParent()->sectionIndex; } size_t VersionTableSection::getSize() const { - return (getPartition().DynSymTab->getSymbols().size() + 1) * 2; + return (getPartition().dynSymTab->getSymbols().size() + 1) * 2; } -void VersionTableSection::writeTo(uint8_t *Buf) { - Buf += 2; - for (const SymbolTableEntry &S : getPartition().DynSymTab->getSymbols()) { - write16(Buf, S.Sym->VersionId); - Buf += 2; +void VersionTableSection::writeTo(uint8_t *buf) { + buf += 2; + for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) { + write16(buf, s.sym->versionId); + buf += 2; } } bool VersionTableSection::isNeeded() const { - return getPartition().VerDef || getPartition().VerNeed->isNeeded(); + return getPartition().verDef || getPartition().verNeed->isNeeded(); } -void elf::addVerneed(Symbol *SS) { - auto &File = cast(*SS->File); - if (SS->VerdefIndex == VER_NDX_GLOBAL) { - SS->VersionId = VER_NDX_GLOBAL; +void elf::addVerneed(Symbol *ss) { + auto &file = cast(*ss->file); + if (ss->verdefIndex == VER_NDX_GLOBAL) { + ss->versionId = VER_NDX_GLOBAL; return; } - if (File.Vernauxs.empty()) - File.Vernauxs.resize(File.Verdefs.size()); + if (file.vernauxs.empty()) + file.vernauxs.resize(file.verdefs.size()); // Select a version identifier for the vernaux data structure, if we haven't // already allocated one. The verdef identifiers cover the range // [1..getVerDefNum()]; this causes the vernaux identifiers to start from // getVerDefNum()+1. - if (File.Vernauxs[SS->VerdefIndex] == 0) - File.Vernauxs[SS->VerdefIndex] = ++SharedFile::VernauxNum + getVerDefNum(); + if (file.vernauxs[ss->verdefIndex] == 0) + file.vernauxs[ss->verdefIndex] = ++SharedFile::vernauxNum + getVerDefNum(); - SS->VersionId = File.Vernauxs[SS->VerdefIndex]; + ss->versionId = file.vernauxs[ss->verdefIndex]; } template @@ -2854,107 +2854,107 @@ ".gnu.version_r") {} template void VersionNeedSection::finalizeContents() { - for (SharedFile *F : SharedFiles) { - if (F->Vernauxs.empty()) + for (SharedFile *f : sharedFiles) { + if (f->vernauxs.empty()) continue; - Verneeds.emplace_back(); - Verneed &VN = Verneeds.back(); - VN.NameStrTab = getPartition().DynStrTab->addString(F->SoName); - for (unsigned I = 0; I != F->Vernauxs.size(); ++I) { - if (F->Vernauxs[I] == 0) + verneeds.emplace_back(); + Verneed &vn = verneeds.back(); + vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); + for (unsigned i = 0; i != f->vernauxs.size(); ++i) { + if (f->vernauxs[i] == 0) continue; - auto *Verdef = - reinterpret_cast(F->Verdefs[I]); - VN.Vernauxs.push_back( - {Verdef->vd_hash, F->Vernauxs[I], - getPartition().DynStrTab->addString(F->getStringTable().data() + - Verdef->getAux()->vda_name)}); + auto *verdef = + reinterpret_cast(f->verdefs[i]); + vn.vernauxs.push_back( + {verdef->vd_hash, f->vernauxs[i], + getPartition().dynStrTab->addString(f->getStringTable().data() + + verdef->getAux()->vda_name)}); } } - if (OutputSection *Sec = getPartition().DynStrTab->getParent()) - getParent()->Link = Sec->SectionIndex; - getParent()->Info = Verneeds.size(); + if (OutputSection *sec = getPartition().dynStrTab->getParent()) + getParent()->link = sec->sectionIndex; + getParent()->info = verneeds.size(); } -template void VersionNeedSection::writeTo(uint8_t *Buf) { +template void VersionNeedSection::writeTo(uint8_t *buf) { // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. - auto *Verneed = reinterpret_cast(Buf); - auto *Vernaux = reinterpret_cast(Verneed + Verneeds.size()); + auto *verneed = reinterpret_cast(buf); + auto *vernaux = reinterpret_cast(verneed + verneeds.size()); - for (auto &VN : Verneeds) { + for (auto &vn : verneeds) { // Create an Elf_Verneed for this DSO. - Verneed->vn_version = 1; - Verneed->vn_cnt = VN.Vernauxs.size(); - Verneed->vn_file = VN.NameStrTab; - Verneed->vn_aux = - reinterpret_cast(Vernaux) - reinterpret_cast(Verneed); - Verneed->vn_next = sizeof(Elf_Verneed); - ++Verneed; + verneed->vn_version = 1; + verneed->vn_cnt = vn.vernauxs.size(); + verneed->vn_file = vn.nameStrTab; + verneed->vn_aux = + reinterpret_cast(vernaux) - reinterpret_cast(verneed); + verneed->vn_next = sizeof(Elf_Verneed); + ++verneed; // Create the Elf_Vernauxs for this Elf_Verneed. - for (auto &VNA : VN.Vernauxs) { - Vernaux->vna_hash = VNA.Hash; - Vernaux->vna_flags = 0; - Vernaux->vna_other = VNA.VerneedIndex; - Vernaux->vna_name = VNA.NameStrTab; - Vernaux->vna_next = sizeof(Elf_Vernaux); - ++Vernaux; + for (auto &vna : vn.vernauxs) { + vernaux->vna_hash = vna.hash; + vernaux->vna_flags = 0; + vernaux->vna_other = vna.verneedIndex; + vernaux->vna_name = vna.nameStrTab; + vernaux->vna_next = sizeof(Elf_Vernaux); + ++vernaux; } - Vernaux[-1].vna_next = 0; + vernaux[-1].vna_next = 0; } - Verneed[-1].vn_next = 0; + verneed[-1].vn_next = 0; } template size_t VersionNeedSection::getSize() const { - return Verneeds.size() * sizeof(Elf_Verneed) + - SharedFile::VernauxNum * sizeof(Elf_Vernaux); + return verneeds.size() * sizeof(Elf_Verneed) + + SharedFile::vernauxNum * sizeof(Elf_Vernaux); } template bool VersionNeedSection::isNeeded() const { - return SharedFile::VernauxNum != 0; + return SharedFile::vernauxNum != 0; } -void MergeSyntheticSection::addSection(MergeInputSection *MS) { - MS->Parent = this; - Sections.push_back(MS); - assert(Alignment == MS->Alignment || !(MS->Flags & SHF_STRINGS)); - Alignment = std::max(Alignment, MS->Alignment); +void MergeSyntheticSection::addSection(MergeInputSection *ms) { + ms->parent = this; + sections.push_back(ms); + assert(alignment == ms->alignment || !(ms->flags & SHF_STRINGS)); + alignment = std::max(alignment, ms->alignment); } -MergeTailSection::MergeTailSection(StringRef Name, uint32_t Type, - uint64_t Flags, uint32_t Alignment) - : MergeSyntheticSection(Name, Type, Flags, Alignment), - Builder(StringTableBuilder::RAW, Alignment) {} +MergeTailSection::MergeTailSection(StringRef name, uint32_t type, + uint64_t flags, uint32_t alignment) + : MergeSyntheticSection(name, type, flags, alignment), + builder(StringTableBuilder::RAW, alignment) {} -size_t MergeTailSection::getSize() const { return Builder.getSize(); } +size_t MergeTailSection::getSize() const { return builder.getSize(); } -void MergeTailSection::writeTo(uint8_t *Buf) { Builder.write(Buf); } +void MergeTailSection::writeTo(uint8_t *buf) { builder.write(buf); } void MergeTailSection::finalizeContents() { // Add all string pieces to the string table builder to create section // contents. - for (MergeInputSection *Sec : Sections) - for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) - if (Sec->Pieces[I].Live) - Builder.add(Sec->getData(I)); + for (MergeInputSection *sec : sections) + for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) + if (sec->pieces[i].live) + builder.add(sec->getData(i)); // Fix the string table content. After this, the contents will never change. - Builder.finalize(); + builder.finalize(); // finalize() fixed tail-optimized strings, so we can now get // offsets of strings. Get an offset for each string and save it // to a corresponding StringPiece for easy access. - for (MergeInputSection *Sec : Sections) - for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) - if (Sec->Pieces[I].Live) - Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I)); + for (MergeInputSection *sec : sections) + for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) + if (sec->pieces[i].live) + sec->pieces[i].outputOff = builder.getOffset(sec->getData(i)); } -void MergeNoTailSection::writeTo(uint8_t *Buf) { - for (size_t I = 0; I < NumShards; ++I) - Shards[I].write(Buf + ShardOffsets[I]); +void MergeNoTailSection::writeTo(uint8_t *buf) { + for (size_t i = 0; i < numShards; ++i) + shards[i].write(buf + shardOffsets[i]); } // This function is very hot (i.e. it can take several seconds to finish) @@ -2967,68 +2967,68 @@ // We do it in parallel. void MergeNoTailSection::finalizeContents() { // Initializes string table builders. - for (size_t I = 0; I < NumShards; ++I) - Shards.emplace_back(StringTableBuilder::RAW, Alignment); + for (size_t i = 0; i < numShards; ++i) + shards.emplace_back(StringTableBuilder::RAW, alignment); // Concurrency level. Must be a power of 2 to avoid expensive modulo // operations in the following tight loop. - size_t Concurrency = 1; + size_t concurrency = 1; if (ThreadsEnabled) - Concurrency = - std::min(PowerOf2Floor(hardware_concurrency()), NumShards); + concurrency = + std::min(PowerOf2Floor(hardware_concurrency()), numShards); // Add section pieces to the builders. - parallelForEachN(0, Concurrency, [&](size_t ThreadId) { - for (MergeInputSection *Sec : Sections) { - for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) { - if (!Sec->Pieces[I].Live) + parallelForEachN(0, concurrency, [&](size_t threadId) { + for (MergeInputSection *sec : sections) { + for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) { + if (!sec->pieces[i].live) continue; - size_t ShardId = getShardId(Sec->Pieces[I].Hash); - if ((ShardId & (Concurrency - 1)) == ThreadId) - Sec->Pieces[I].OutputOff = Shards[ShardId].add(Sec->getData(I)); + size_t shardId = getShardId(sec->pieces[i].hash); + if ((shardId & (concurrency - 1)) == threadId) + sec->pieces[i].outputOff = shards[shardId].add(sec->getData(i)); } } }); // Compute an in-section offset for each shard. - size_t Off = 0; - for (size_t I = 0; I < NumShards; ++I) { - Shards[I].finalizeInOrder(); - if (Shards[I].getSize() > 0) - Off = alignTo(Off, Alignment); - ShardOffsets[I] = Off; - Off += Shards[I].getSize(); + size_t off = 0; + for (size_t i = 0; i < numShards; ++i) { + shards[i].finalizeInOrder(); + if (shards[i].getSize() > 0) + off = alignTo(off, alignment); + shardOffsets[i] = off; + off += shards[i].getSize(); } - Size = Off; + size = off; // So far, section pieces have offsets from beginning of shards, but // we want offsets from beginning of the whole section. Fix them. - parallelForEach(Sections, [&](MergeInputSection *Sec) { - for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) - if (Sec->Pieces[I].Live) - Sec->Pieces[I].OutputOff += - ShardOffsets[getShardId(Sec->Pieces[I].Hash)]; + parallelForEach(sections, [&](MergeInputSection *sec) { + for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) + if (sec->pieces[i].live) + sec->pieces[i].outputOff += + shardOffsets[getShardId(sec->pieces[i].hash)]; }); } -static MergeSyntheticSection *createMergeSynthetic(StringRef Name, - uint32_t Type, - uint64_t Flags, - uint32_t Alignment) { - bool ShouldTailMerge = (Flags & SHF_STRINGS) && Config->Optimize >= 2; - if (ShouldTailMerge) - return make(Name, Type, Flags, Alignment); - return make(Name, Type, Flags, Alignment); +static MergeSyntheticSection *createMergeSynthetic(StringRef name, + uint32_t type, + uint64_t flags, + uint32_t alignment) { + bool shouldTailMerge = (flags & SHF_STRINGS) && config->optimize >= 2; + if (shouldTailMerge) + return make(name, type, flags, alignment); + return make(name, type, flags, alignment); } template void elf::splitSections() { // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - parallelForEach(InputSections, [](InputSectionBase *Sec) { - if (auto *S = dyn_cast(Sec)) - S->splitIntoPieces(); - else if (auto *Eh = dyn_cast(Sec)) - Eh->split(); + parallelForEach(inputSections, [](InputSectionBase *sec) { + if (auto *s = dyn_cast(sec)) + s->splitIntoPieces(); + else if (auto *eh = dyn_cast(sec)) + eh->split(); }); } @@ -3040,22 +3040,22 @@ // that it replaces. It then finalizes each synthetic section in order // to compute an output offset for each piece of each input section. void elf::mergeSections() { - std::vector MergeSections; - for (InputSectionBase *&S : InputSections) { - MergeInputSection *MS = dyn_cast(S); - if (!MS) + std::vector mergeSections; + for (InputSectionBase *&s : inputSections) { + MergeInputSection *ms = dyn_cast(s); + if (!ms) continue; // We do not want to handle sections that are not alive, so just remove // them instead of trying to merge. - if (!MS->isLive()) { - S = nullptr; + if (!ms->isLive()) { + s = nullptr; continue; } - StringRef OutsecName = getOutputSectionName(MS); + StringRef outsecName = getOutputSectionName(ms); - auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) { + auto i = llvm::find_if(mergeSections, [=](MergeSyntheticSection *sec) { // While we could create a single synthetic section for two different // values of Entsize, it is better to take Entsize into consideration. // @@ -3066,55 +3066,55 @@ // section. // // SHF_STRINGS section with different alignments should not be merged. - return Sec->Name == OutsecName && Sec->Flags == MS->Flags && - Sec->Entsize == MS->Entsize && - (Sec->Alignment == MS->Alignment || !(Sec->Flags & SHF_STRINGS)); + return sec->name == outsecName && sec->flags == ms->flags && + sec->entsize == ms->entsize && + (sec->alignment == ms->alignment || !(sec->flags & SHF_STRINGS)); }); - if (I == MergeSections.end()) { - MergeSyntheticSection *Syn = - createMergeSynthetic(OutsecName, MS->Type, MS->Flags, MS->Alignment); - MergeSections.push_back(Syn); - I = std::prev(MergeSections.end()); - S = Syn; - Syn->Entsize = MS->Entsize; + if (i == mergeSections.end()) { + MergeSyntheticSection *syn = + createMergeSynthetic(outsecName, ms->type, ms->flags, ms->alignment); + mergeSections.push_back(syn); + i = std::prev(mergeSections.end()); + s = syn; + syn->entsize = ms->entsize; } else { - S = nullptr; + s = nullptr; } - (*I)->addSection(MS); + (*i)->addSection(ms); } - for (auto *MS : MergeSections) - MS->finalizeContents(); + for (auto *ms : mergeSections) + ms->finalizeContents(); - std::vector &V = InputSections; - V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); + std::vector &v = inputSections; + v.erase(std::remove(v.begin(), v.end(), nullptr), v.end()); } MipsRldMapSection::MipsRldMapSection() - : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, + : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, ".rld_map") {} ARMExidxSyntheticSection::ARMExidxSyntheticSection() : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, - Config->Wordsize, ".ARM.exidx") {} + config->wordsize, ".ARM.exidx") {} -static InputSection *findExidxSection(InputSection *IS) { - for (InputSection *D : IS->DependentSections) - if (D->Type == SHT_ARM_EXIDX) - return D; +static InputSection *findExidxSection(InputSection *isec) { + for (InputSection *d : isec->dependentSections) + if (d->type == SHT_ARM_EXIDX) + return d; return nullptr; } -bool ARMExidxSyntheticSection::addSection(InputSection *IS) { - if (IS->Type == SHT_ARM_EXIDX) { - ExidxSections.push_back(IS); +bool ARMExidxSyntheticSection::addSection(InputSection *isec) { + if (isec->type == SHT_ARM_EXIDX) { + exidxSections.push_back(isec); return true; } - if ((IS->Flags & SHF_ALLOC) && (IS->Flags & SHF_EXECINSTR) && - IS->getSize() > 0) { - ExecutableSections.push_back(IS); - if (Empty && findExidxSection(IS)) - Empty = false; + if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) && + isec->getSize() > 0) { + executableSections.push_back(isec); + if (empty && findExidxSection(isec)) + empty = false; return false; } @@ -3123,9 +3123,9 @@ // and we would have to erase at a late stage relocations from merged entries. // Given that exception tables are already position independent and a binary // analyzer could derive the relocations we choose to erase the relocations. - if (Config->EmitRelocs && IS->Type == SHT_REL) - if (InputSectionBase *EX = IS->getRelocatedSection()) - if (isa(EX) && EX->Type == SHT_ARM_EXIDX) + if (config->emitRelocs && isec->type == SHT_REL) + if (InputSectionBase *ex = isec->getRelocatedSection()) + if (isa(ex) && ex->type == SHT_ARM_EXIDX) return true; return false; @@ -3133,8 +3133,8 @@ // References to .ARM.Extab Sections have bit 31 clear and are not the // special EXIDX_CANTUNWIND bit-pattern. -static bool isExtabRef(uint32_t Unwind) { - return (Unwind & 0x80000000) == 0 && Unwind != 0x1; +static bool isExtabRef(uint32_t unwind) { + return (unwind & 0x80000000) == 0 && unwind != 0x1; } // Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx @@ -3142,18 +3142,18 @@ // unwinding instructions in Cur are identical to Prev. Linker generated // EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an // InputSection. -static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { +static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { struct ExidxEntry { - ulittle32_t Fn; - ulittle32_t Unwind; + ulittle32_t fn; + ulittle32_t unwind; }; // Get the last table Entry from the previous .ARM.exidx section. If Prev is // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry. - ExidxEntry PrevEntry = {ulittle32_t(0), ulittle32_t(1)}; - if (Prev) - PrevEntry = Prev->getDataAs().back(); - if (isExtabRef(PrevEntry.Unwind)) + ExidxEntry prevEntry = {ulittle32_t(0), ulittle32_t(1)}; + if (prev) + prevEntry = prev->getDataAs().back(); + if (isExtabRef(prevEntry.unwind)) return false; // We consider the unwind instructions of an .ARM.exidx table entry @@ -3165,11 +3165,11 @@ // are identical is high. // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry. - if (Cur == nullptr) - return PrevEntry.Unwind == 1; + if (cur == nullptr) + return prevEntry.unwind == 1; - for (const ExidxEntry Entry : Cur->getDataAs()) - if (isExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) + for (const ExidxEntry entry : cur->getDataAs()) + if (isExtabRef(entry.unwind) || entry.unwind != prevEntry.unwind) return false; // All table entries in this .ARM.exidx Section can be merged into the @@ -3187,51 +3187,51 @@ // Sort the executable sections that may or may not have associated // .ARM.exidx sections by order of ascending address. This requires the // relative positions of InputSections to be known. - auto CompareByFilePosition = [](const InputSection *A, - const InputSection *B) { - OutputSection *AOut = A->getParent(); - OutputSection *BOut = B->getParent(); - - if (AOut != BOut) - return AOut->SectionIndex < BOut->SectionIndex; - return A->OutSecOff < B->OutSecOff; + auto compareByFilePosition = [](const InputSection *a, + const InputSection *b) { + OutputSection *aOut = a->getParent(); + OutputSection *bOut = b->getParent(); + + if (aOut != bOut) + return aOut->sectionIndex < bOut->sectionIndex; + return a->outSecOff < b->outSecOff; }; - llvm::stable_sort(ExecutableSections, CompareByFilePosition); - Sentinel = ExecutableSections.back(); + llvm::stable_sort(executableSections, compareByFilePosition); + sentinel = executableSections.back(); // Optionally merge adjacent duplicate entries. - if (Config->MergeArmExidx) { - std::vector SelectedSections; - SelectedSections.reserve(ExecutableSections.size()); - SelectedSections.push_back(ExecutableSections[0]); - size_t Prev = 0; - for (size_t I = 1; I < ExecutableSections.size(); ++I) { - InputSection *EX1 = findExidxSection(ExecutableSections[Prev]); - InputSection *EX2 = findExidxSection(ExecutableSections[I]); - if (!isDuplicateArmExidxSec(EX1, EX2)) { - SelectedSections.push_back(ExecutableSections[I]); - Prev = I; + if (config->mergeArmExidx) { + std::vector selectedSections; + selectedSections.reserve(executableSections.size()); + selectedSections.push_back(executableSections[0]); + size_t prev = 0; + for (size_t i = 1; i < executableSections.size(); ++i) { + InputSection *ex1 = findExidxSection(executableSections[prev]); + InputSection *ex2 = findExidxSection(executableSections[i]); + if (!isDuplicateArmExidxSec(ex1, ex2)) { + selectedSections.push_back(executableSections[i]); + prev = i; } } - ExecutableSections = std::move(SelectedSections); + executableSections = std::move(selectedSections); } - size_t Offset = 0; - Size = 0; - for (InputSection *IS : ExecutableSections) { - if (InputSection *D = findExidxSection(IS)) { - D->OutSecOff = Offset; - D->Parent = getParent(); - Offset += D->getSize(); + size_t offset = 0; + size = 0; + for (InputSection *isec : executableSections) { + if (InputSection *d = findExidxSection(isec)) { + d->outSecOff = offset; + d->parent = getParent(); + offset += d->getSize(); } else { - Offset += 8; + offset += 8; } } // Size includes Sentinel. - Size = Offset + 8; + size = offset + 8; } InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const { - return ExecutableSections.front(); + return executableSections.front(); } // To write the .ARM.exidx table from the ExecutableSections we have three cases @@ -3243,75 +3243,75 @@ // section is to terminate the address range of the previous entry. // 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of // the table to terminate the address range of the final entry. -void ARMExidxSyntheticSection::writeTo(uint8_t *Buf) { +void ARMExidxSyntheticSection::writeTo(uint8_t *buf) { - const uint8_t CantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target + const uint8_t cantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target 1, 0, 0, 0}; // EXIDX_CANTUNWIND - uint64_t Offset = 0; - for (InputSection *IS : ExecutableSections) { - assert(IS->getParent() != nullptr); - if (InputSection *D = findExidxSection(IS)) { - memcpy(Buf + Offset, D->data().data(), D->data().size()); - D->relocateAlloc(Buf, Buf + D->getSize()); - Offset += D->getSize(); + uint64_t offset = 0; + for (InputSection *isec : executableSections) { + assert(isec->getParent() != nullptr); + if (InputSection *d = findExidxSection(isec)) { + memcpy(buf + offset, d->data().data(), d->data().size()); + d->relocateAlloc(buf, buf + d->getSize()); + offset += d->getSize(); } else { // A Linker generated CANTUNWIND section. - memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData)); - uint64_t S = IS->getVA(); - uint64_t P = getVA() + Offset; - Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P); - Offset += 8; + memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData)); + uint64_t s = isec->getVA(); + uint64_t p = getVA() + offset; + target->relocateOne(buf + offset, R_ARM_PREL31, s - p); + offset += 8; } } // Write Sentinel. - memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData)); - uint64_t S = Sentinel->getVA(Sentinel->getSize()); - uint64_t P = getVA() + Offset; - Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P); - assert(Size == Offset + 8); + memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData)); + uint64_t s = sentinel->getVA(sentinel->getSize()); + uint64_t p = getVA() + offset; + target->relocateOne(buf + offset, R_ARM_PREL31, s - p); + assert(size == offset + 8); } -bool ARMExidxSyntheticSection::classof(const SectionBase *D) { - return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX; +bool ARMExidxSyntheticSection::classof(const SectionBase *d) { + return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX; } -ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off) +ThunkSection::ThunkSection(OutputSection *os, uint64_t off) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, - Config->Wordsize, ".text.thunk") { - this->Parent = OS; - this->OutSecOff = Off; + config->wordsize, ".text.thunk") { + this->parent = os; + this->outSecOff = off; } -void ThunkSection::addThunk(Thunk *T) { - Thunks.push_back(T); - T->addSymbols(*this); +void ThunkSection::addThunk(Thunk *t) { + thunks.push_back(t); + t->addSymbols(*this); } -void ThunkSection::writeTo(uint8_t *Buf) { - for (Thunk *T : Thunks) - T->writeTo(Buf + T->Offset); +void ThunkSection::writeTo(uint8_t *buf) { + for (Thunk *t : thunks) + t->writeTo(buf + t->offset); } InputSection *ThunkSection::getTargetInputSection() const { - if (Thunks.empty()) + if (thunks.empty()) return nullptr; - const Thunk *T = Thunks.front(); - return T->getTargetInputSection(); + const Thunk *t = thunks.front(); + return t->getTargetInputSection(); } bool ThunkSection::assignOffsets() { - uint64_t Off = 0; - for (Thunk *T : Thunks) { - Off = alignTo(Off, T->Alignment); - T->setOffset(Off); - uint32_t Size = T->size(); - T->getThunkTargetSym()->Size = Size; - Off += Size; - } - bool Changed = Off != Size; - Size = Off; - return Changed; + uint64_t off = 0; + for (Thunk *t : thunks) { + off = alignTo(off, t->alignment); + t->setOffset(off); + uint32_t size = t->size(); + t->getThunkTargetSym()->size = size; + off += size; + } + bool changed = off != size; + size = off; + return changed; } PPC32Got2Section::PPC32Got2Section() @@ -3320,10 +3320,10 @@ bool PPC32Got2Section::isNeeded() const { // See the comment below. This is not needed if there is no other // InputSection. - for (BaseCommand *Base : getParent()->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - for (InputSection *IS : ISD->Sections) - if (IS != this) + for (BaseCommand *base : getParent()->sectionCommands) + if (auto *isd = dyn_cast(base)) + for (InputSection *isec : isd->sections) + if (isec != this) return true; return false; } @@ -3333,14 +3333,14 @@ // .got2 . This function computes OutSecOff of each .got2 to be used in // PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is // to collect input sections named ".got2". - uint32_t Offset = 0; - for (BaseCommand *Base : getParent()->SectionCommands) - if (auto *ISD = dyn_cast(Base)) { - for (InputSection *IS : ISD->Sections) { - if (IS == this) + uint32_t offset = 0; + for (BaseCommand *base : getParent()->sectionCommands) + if (auto *isd = dyn_cast(base)) { + for (InputSection *isec : isd->sections) { + if (isec == this) continue; - IS->File->PPC32Got2OutSecOff = Offset; - Offset += (uint32_t)IS->getSize(); + isec->file->ppc32Got2OutSecOff = offset; + offset += (uint32_t)isec->getSize(); } } } @@ -3351,33 +3351,33 @@ // allocated and filled in by the dynamic linker. PPC64LongBranchTargetSection::PPC64LongBranchTargetSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, - Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8, + config->isPic ? SHT_NOBITS : SHT_PROGBITS, 8, ".branch_lt") {} -void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) { - assert(Sym.PPC64BranchltIndex == 0xffff); - Sym.PPC64BranchltIndex = Entries.size(); - Entries.push_back(&Sym); +void PPC64LongBranchTargetSection::addEntry(Symbol &sym) { + assert(sym.ppc64BranchltIndex == 0xffff); + sym.ppc64BranchltIndex = entries.size(); + entries.push_back(&sym); } size_t PPC64LongBranchTargetSection::getSize() const { - return Entries.size() * 8; + return entries.size() * 8; } -void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) { +void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) { // If linking non-pic we have the final addresses of the targets and they get // written to the table directly. For pic the dynamic linker will allocate // the section and fill it it. - if (Config->Pic) + if (config->isPic) return; - for (const Symbol *Sym : Entries) { - assert(Sym->getVA()); + for (const Symbol *sym : entries) { + assert(sym->getVA()); // Need calls to branch to the local entry-point since a long-branch // must be a local-call. - write64(Buf, - Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther)); - Buf += 8; + write64(buf, + sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(sym->stOther)); + buf += 8; } } @@ -3388,85 +3388,85 @@ // only gets set to true once `finalizeSections()` is called after thunk // creation. Becuase of this, if we don't create any long-branch thunks we end // up with an empty .branch_lt section in the binary. - return !Finalized || !Entries.empty(); + return !finalized || !entries.empty(); } RISCVSdataSection::RISCVSdataSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 1, ".sdata") {} bool RISCVSdataSection::isNeeded() const { - if (!ElfSym::RISCVGlobalPointer) + if (!ElfSym::riscvGlobalPointer) return false; // __global_pointer$ is defined relative to .sdata . If the section does not // exist, create a dummy one. - for (BaseCommand *Base : getParent()->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - for (InputSection *IS : ISD->Sections) - if (IS != this) + for (BaseCommand *base : getParent()->sectionCommands) + if (auto *isd = dyn_cast(base)) + for (InputSection *isec : isd->sections) + if (isec != this) return false; return true; } static uint8_t getAbiVersion() { // MIPS non-PIC executable gets ABI version 1. - if (Config->EMachine == EM_MIPS) { - if (!Config->Pic && !Config->Relocatable && - (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC) + if (config->emachine == EM_MIPS) { + if (!config->isPic && !config->relocatable && + (config->eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC) return 1; return 0; } - if (Config->EMachine == EM_AMDGPU) { - uint8_t Ver = ObjectFiles[0]->ABIVersion; - for (InputFile *File : makeArrayRef(ObjectFiles).slice(1)) - if (File->ABIVersion != Ver) - error("incompatible ABI version: " + toString(File)); - return Ver; + if (config->emachine == EM_AMDGPU) { + uint8_t ver = objectFiles[0]->abiVersion; + for (InputFile *file : makeArrayRef(objectFiles).slice(1)) + if (file->abiVersion != ver) + error("incompatible ABI version: " + toString(file)); + return ver; } return 0; } -template void elf::writeEhdr(uint8_t *Buf, Partition &Part) { +template void elf::writeEhdr(uint8_t *buf, Partition &part) { // For executable segments, the trap instructions are written before writing // the header. Setting Elf header bytes to zero ensures that any unused bytes // in header are zero-cleared, instead of having trap instructions. - memset(Buf, 0, sizeof(typename ELFT::Ehdr)); - memcpy(Buf, "\177ELF", 4); + memset(buf, 0, sizeof(typename ELFT::Ehdr)); + memcpy(buf, "\177ELF", 4); - auto *EHdr = reinterpret_cast(Buf); - EHdr->e_ident[EI_CLASS] = Config->Is64 ? ELFCLASS64 : ELFCLASS32; - EHdr->e_ident[EI_DATA] = Config->IsLE ? ELFDATA2LSB : ELFDATA2MSB; - EHdr->e_ident[EI_VERSION] = EV_CURRENT; - EHdr->e_ident[EI_OSABI] = Config->OSABI; - EHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); - EHdr->e_machine = Config->EMachine; - EHdr->e_version = EV_CURRENT; - EHdr->e_flags = Config->EFlags; - EHdr->e_ehsize = sizeof(typename ELFT::Ehdr); - EHdr->e_phnum = Part.Phdrs.size(); - EHdr->e_shentsize = sizeof(typename ELFT::Shdr); - - if (!Config->Relocatable) { - EHdr->e_phoff = sizeof(typename ELFT::Ehdr); - EHdr->e_phentsize = sizeof(typename ELFT::Phdr); + auto *eHdr = reinterpret_cast(buf); + eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS64 : ELFCLASS32; + eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB : ELFDATA2MSB; + eHdr->e_ident[EI_VERSION] = EV_CURRENT; + eHdr->e_ident[EI_OSABI] = config->osabi; + eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); + eHdr->e_machine = config->emachine; + eHdr->e_version = EV_CURRENT; + eHdr->e_flags = config->eflags; + eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); + eHdr->e_phnum = part.phdrs.size(); + eHdr->e_shentsize = sizeof(typename ELFT::Shdr); + + if (!config->relocatable) { + eHdr->e_phoff = sizeof(typename ELFT::Ehdr); + eHdr->e_phentsize = sizeof(typename ELFT::Phdr); } } -template void elf::writePhdrs(uint8_t *Buf, Partition &Part) { +template void elf::writePhdrs(uint8_t *buf, Partition &part) { // Write the program header table. - auto *HBuf = reinterpret_cast(Buf); - for (PhdrEntry *P : Part.Phdrs) { - HBuf->p_type = P->p_type; - HBuf->p_flags = P->p_flags; - HBuf->p_offset = P->p_offset; - HBuf->p_vaddr = P->p_vaddr; - HBuf->p_paddr = P->p_paddr; - HBuf->p_filesz = P->p_filesz; - HBuf->p_memsz = P->p_memsz; - HBuf->p_align = P->p_align; - ++HBuf; + auto *hBuf = reinterpret_cast(buf); + for (PhdrEntry *p : part.phdrs) { + hBuf->p_type = p->p_type; + hBuf->p_flags = p->p_flags; + hBuf->p_offset = p->p_offset; + hBuf->p_vaddr = p->p_vaddr; + hBuf->p_paddr = p->p_paddr; + hBuf->p_filesz = p->p_filesz; + hBuf->p_memsz = p->p_memsz; + hBuf->p_align = p->p_align; + ++hBuf; } } @@ -3480,12 +3480,12 @@ } template -void PartitionElfHeaderSection::writeTo(uint8_t *Buf) { - writeEhdr(Buf, getPartition()); +void PartitionElfHeaderSection::writeTo(uint8_t *buf) { + writeEhdr(buf, getPartition()); // Loadable partitions are always ET_DYN. - auto *EHdr = reinterpret_cast(Buf); - EHdr->e_type = ET_DYN; + auto *eHdr = reinterpret_cast(buf); + eHdr->e_type = ET_DYN; } template @@ -3494,45 +3494,45 @@ template size_t PartitionProgramHeadersSection::getSize() const { - return sizeof(typename ELFT::Phdr) * getPartition().Phdrs.size(); + return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size(); } template -void PartitionProgramHeadersSection::writeTo(uint8_t *Buf) { - writePhdrs(Buf, getPartition()); +void PartitionProgramHeadersSection::writeTo(uint8_t *buf) { + writePhdrs(buf, getPartition()); } PartitionIndexSection::PartitionIndexSection() : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".rodata") {} size_t PartitionIndexSection::getSize() const { - return 12 * (Partitions.size() - 1); + return 12 * (partitions.size() - 1); } void PartitionIndexSection::finalizeContents() { - for (size_t I = 1; I != Partitions.size(); ++I) - Partitions[I].NameStrTab = Main->DynStrTab->addString(Partitions[I].Name); + for (size_t i = 1; i != partitions.size(); ++i) + partitions[i].nameStrTab = mainPart->dynStrTab->addString(partitions[i].name); } -void PartitionIndexSection::writeTo(uint8_t *Buf) { - uint64_t VA = getVA(); - for (size_t I = 1; I != Partitions.size(); ++I) { - write32(Buf, Main->DynStrTab->getVA() + Partitions[I].NameStrTab - VA); - write32(Buf + 4, Partitions[I].ElfHeader->getVA() - (VA + 4)); +void PartitionIndexSection::writeTo(uint8_t *buf) { + uint64_t va = getVA(); + for (size_t i = 1; i != partitions.size(); ++i) { + write32(buf, mainPart->dynStrTab->getVA() + partitions[i].nameStrTab - va); + write32(buf + 4, partitions[i].elfHeader->getVA() - (va + 4)); - SyntheticSection *Next = - I == Partitions.size() - 1 ? In.PartEnd : Partitions[I + 1].ElfHeader; - write32(Buf + 8, Next->getVA() - Partitions[I].ElfHeader->getVA()); + SyntheticSection *next = + i == partitions.size() - 1 ? in.partEnd : partitions[i + 1].elfHeader; + write32(buf + 8, next->getVA() - partitions[i].elfHeader->getVA()); - VA += 12; - Buf += 12; + va += 12; + buf += 12; } } -InStruct elf::In; +InStruct elf::in; -std::vector elf::Partitions; -Partition *elf::Main; +std::vector elf::partitions; +Partition *elf::mainPart; template GdbIndexSection *GdbIndexSection::create(); template GdbIndexSection *GdbIndexSection::create(); Index: lld/trunk/ELF/Target.h =================================================================== --- lld/trunk/ELF/Target.h +++ lld/trunk/ELF/Target.h @@ -16,7 +16,7 @@ #include namespace lld { -std::string toString(elf::RelType Type); +std::string toString(elf::RelType type); namespace elf { class Defined; @@ -26,39 +26,39 @@ class TargetInfo { public: virtual uint32_t calcEFlags() const { return 0; } - virtual RelExpr getRelExpr(RelType Type, const Symbol &S, - const uint8_t *Loc) const = 0; - virtual RelType getDynRel(RelType Type) const { return 0; } - virtual void writeGotPltHeader(uint8_t *Buf) const {} - virtual void writeGotHeader(uint8_t *Buf) const {} - virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {}; - virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const; - virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const; - virtual int getTlsGdRelaxSkip(RelType Type) const { return 1; } + virtual RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const = 0; + virtual RelType getDynRel(RelType type) const { return 0; } + virtual void writeGotPltHeader(uint8_t *buf) const {} + virtual void writeGotHeader(uint8_t *buf) const {} + virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {}; + virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const; + virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const; + virtual int getTlsGdRelaxSkip(RelType type) const { return 1; } // If lazy binding is supported, the first entry of the PLT has code // to call the dynamic linker to resolve PLT entries the first time // they are called. This function writes that code. - virtual void writePltHeader(uint8_t *Buf) const {} + virtual void writePltHeader(uint8_t *buf) const {} - virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, - uint64_t PltEntryAddr, int32_t Index, - unsigned RelOff) const {} - virtual void addPltHeaderSymbols(InputSection &IS) const {} - virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {} + virtual void writePlt(uint8_t *buf, uint64_t gotEntryAddr, + uint64_t pltEntryAddr, int32_t index, + unsigned relOff) const {} + virtual void addPltHeaderSymbols(InputSection &isec) const {} + virtual void addPltSymbols(InputSection &isec, uint64_t off) const {} // Returns true if a relocation only uses the low bits of a value such that // all those bits are in the same page. For example, if the relocation // only uses the low 12 bits in a system with 4k pages. If this is true, the // bits will always have the same value at runtime and we don't have to emit // a dynamic relocation. - virtual bool usesOnlyLowPageBits(RelType Type) const; + virtual bool usesOnlyLowPageBits(RelType type) const; // Decide whether a Thunk is needed for the relocation from File // targeting S. - virtual bool needsThunk(RelExpr Expr, RelType RelocType, - const InputFile *File, uint64_t BranchAddr, - const Symbol &S) const; + virtual bool needsThunk(RelExpr expr, RelType relocType, + const InputFile *file, uint64_t branchAddr, + const Symbol &s) const; // On systems with range extensions we place collections of Thunks at // regular spacings that enable the majority of branches reach the Thunks. @@ -70,71 +70,71 @@ // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks. // The symbols st_other flags are needed on PowerPC64 for determining the // offset to the split-stack prologue. - virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const; + virtual bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const; // Return true if we can reach Dst from Src with Relocation RelocType - virtual bool inBranchRange(RelType Type, uint64_t Src, - uint64_t Dst) const; + virtual bool inBranchRange(RelType type, uint64_t src, + uint64_t dst) const; - virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0; + virtual void relocateOne(uint8_t *loc, RelType type, uint64_t val) const = 0; virtual ~TargetInfo(); - unsigned DefaultCommonPageSize = 4096; - unsigned DefaultMaxPageSize = 4096; + unsigned defaultCommonPageSize = 4096; + unsigned defaultMaxPageSize = 4096; uint64_t getImageBase() const; // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got. - bool GotBaseSymInGotPlt = true; + bool gotBaseSymInGotPlt = true; - RelType CopyRel; - RelType GotRel; - RelType NoneRel; - RelType PltRel; - RelType RelativeRel; - RelType IRelativeRel; - RelType SymbolicRel; - RelType TlsDescRel; - RelType TlsGotRel; - RelType TlsModuleIndexRel; - RelType TlsOffsetRel; - unsigned PltEntrySize; - unsigned PltHeaderSize; + RelType copyRel; + RelType gotRel; + RelType noneRel; + RelType pltRel; + RelType relativeRel; + RelType iRelativeRel; + RelType symbolicRel; + RelType tlsDescRel; + RelType tlsGotRel; + RelType tlsModuleIndexRel; + RelType tlsOffsetRel; + unsigned pltEntrySize; + unsigned pltHeaderSize; // At least on x86_64 positions 1 and 2 are used by the first plt entry // to support lazy loading. - unsigned GotPltHeaderEntriesNum = 3; + unsigned gotPltHeaderEntriesNum = 3; // On PPC ELF V2 abi, the first entry in the .got is the .TOC. - unsigned GotHeaderEntriesNum = 0; + unsigned gotHeaderEntriesNum = 0; - bool NeedsThunks = false; + bool needsThunks = false; // A 4-byte field corresponding to one or more trap instructions, used to pad // executable OutputSections. - std::array TrapInstr; + std::array trapInstr; // If a target needs to rewrite calls to __morestack to instead call // __morestack_non_split when a split-stack enabled caller calls a // non-split-stack callee this will return true. Otherwise returns false. - bool NeedsMoreStackNonSplit = true; + bool needsMoreStackNonSplit = true; - virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const; - virtual void relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const; - virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const; - virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; - virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; - virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const; + virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const; + virtual void relaxGot(uint8_t *loc, RelType type, uint64_t val) const; + virtual void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const; + virtual void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const; + virtual void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const; + virtual void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const; protected: // On FreeBSD x86_64 the first page cannot be mmaped. // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64 // installs that is 65536, so the first 15 pages cannot be used. // Given that, the smallest value that can be used in here is 0x10000. - uint64_t DefaultImageBase = 0x10000; + uint64_t defaultImageBase = 0x10000; }; TargetInfo *getAArch64TargetInfo(); @@ -152,22 +152,22 @@ template TargetInfo *getMipsTargetInfo(); struct ErrorPlace { - InputSectionBase *IS; - std::string Loc; + InputSectionBase *isec; + std::string loc; }; // Returns input section and corresponding source string for the given location. -ErrorPlace getErrorPlace(const uint8_t *Loc); +ErrorPlace getErrorPlace(const uint8_t *loc); -static inline std::string getErrorLocation(const uint8_t *Loc) { - return getErrorPlace(Loc).Loc; +static inline std::string getErrorLocation(const uint8_t *loc) { + return getErrorPlace(loc).loc; } -void writePPC32GlinkSection(uint8_t *Buf, size_t NumEntries); +void writePPC32GlinkSection(uint8_t *buf, size_t numEntries); -bool tryRelaxPPC64TocIndirection(RelType Type, const Relocation &Rel, - uint8_t *BufLoc); -unsigned getPPCDFormOp(unsigned SecondaryOp); +bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel, + uint8_t *bufLoc); +unsigned getPPCDFormOp(unsigned secondaryOp); // In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first // is a global entry point (GEP) which typically is used to initialize the TOC @@ -176,84 +176,84 @@ // offset between GEP and LEP is encoded in a function's st_other flags. // This function will return the offset (in bytes) from the global entry-point // to the local entry-point. -unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther); +unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther); // Returns true if a relocation is a small code model relocation that accesses // the .toc section. -bool isPPC64SmallCodeModelTocReloc(RelType Type); +bool isPPC64SmallCodeModelTocReloc(RelType type); uint64_t getPPC64TocBase(); -uint64_t getAArch64Page(uint64_t Expr); +uint64_t getAArch64Page(uint64_t expr); -extern const TargetInfo *Target; +extern const TargetInfo *target; TargetInfo *getTarget(); -template bool isMipsPIC(const Defined *Sym); +template bool isMipsPIC(const Defined *sym); -static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V, - int64_t Min, uint64_t Max) { - ErrorPlace ErrPlace = getErrorPlace(Loc); - StringRef Hint; - if (ErrPlace.IS && ErrPlace.IS->Name.startswith(".debug")) - Hint = "; consider recompiling with -fdebug-types-section to reduce size " +static inline void reportRangeError(uint8_t *loc, RelType type, const Twine &v, + int64_t min, uint64_t max) { + ErrorPlace errPlace = getErrorPlace(loc); + StringRef hint; + if (errPlace.isec && errPlace.isec->name.startswith(".debug")) + hint = "; consider recompiling with -fdebug-types-section to reduce size " "of debug sections"; - errorOrWarn(ErrPlace.Loc + "relocation " + lld::toString(Type) + - " out of range: " + V.str() + " is not in [" + Twine(Min).str() + - ", " + Twine(Max).str() + "]" + Hint); + errorOrWarn(errPlace.loc + "relocation " + lld::toString(type) + + " out of range: " + v.str() + " is not in [" + Twine(min).str() + + ", " + Twine(max).str() + "]" + hint); } // Make sure that V can be represented as an N bit signed integer. -inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) { - if (V != llvm::SignExtend64(V, N)) - reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N)); +inline void checkInt(uint8_t *loc, int64_t v, int n, RelType type) { + if (v != llvm::SignExtend64(v, n)) + reportRangeError(loc, type, Twine(v), llvm::minIntN(n), llvm::maxIntN(n)); } // Make sure that V can be represented as an N bit unsigned integer. -inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) { - if ((V >> N) != 0) - reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N)); +inline void checkUInt(uint8_t *loc, uint64_t v, int n, RelType type) { + if ((v >> n) != 0) + reportRangeError(loc, type, Twine(v), 0, llvm::maxUIntN(n)); } // Make sure that V can be represented as an N bit signed or unsigned integer. -inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) { +inline void checkIntUInt(uint8_t *loc, uint64_t v, int n, RelType type) { // For the error message we should cast V to a signed integer so that error // messages show a small negative value rather than an extremely large one - if (V != (uint64_t)llvm::SignExtend64(V, N) && (V >> N) != 0) - reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N), - llvm::maxUIntN(N)); + if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0) + reportRangeError(loc, type, Twine((int64_t)v), llvm::minIntN(n), + llvm::maxUIntN(n)); } -inline void checkAlignment(uint8_t *Loc, uint64_t V, int N, RelType Type) { - if ((V & (N - 1)) != 0) - error(getErrorLocation(Loc) + "improper alignment for relocation " + - lld::toString(Type) + ": 0x" + llvm::utohexstr(V) + - " is not aligned to " + Twine(N) + " bytes"); +inline void checkAlignment(uint8_t *loc, uint64_t v, int n, RelType type) { + if ((v & (n - 1)) != 0) + error(getErrorLocation(loc) + "improper alignment for relocation " + + lld::toString(type) + ": 0x" + llvm::utohexstr(v) + + " is not aligned to " + Twine(n) + " bytes"); } // Endianness-aware read/write. -inline uint16_t read16(const void *P) { - return llvm::support::endian::read16(P, Config->Endianness); +inline uint16_t read16(const void *p) { + return llvm::support::endian::read16(p, config->endianness); } -inline uint32_t read32(const void *P) { - return llvm::support::endian::read32(P, Config->Endianness); +inline uint32_t read32(const void *p) { + return llvm::support::endian::read32(p, config->endianness); } -inline uint64_t read64(const void *P) { - return llvm::support::endian::read64(P, Config->Endianness); +inline uint64_t read64(const void *p) { + return llvm::support::endian::read64(p, config->endianness); } -inline void write16(void *P, uint16_t V) { - llvm::support::endian::write16(P, V, Config->Endianness); +inline void write16(void *p, uint16_t v) { + llvm::support::endian::write16(p, v, config->endianness); } -inline void write32(void *P, uint32_t V) { - llvm::support::endian::write32(P, V, Config->Endianness); +inline void write32(void *p, uint32_t v) { + llvm::support::endian::write32(p, v, config->endianness); } -inline void write64(void *P, uint64_t V) { - llvm::support::endian::write64(P, V, Config->Endianness); +inline void write64(void *p, uint64_t v) { + llvm::support::endian::write64(p, v, config->endianness); } } // namespace elf } // namespace lld Index: lld/trunk/ELF/Target.cpp =================================================================== --- lld/trunk/ELF/Target.cpp +++ lld/trunk/ELF/Target.cpp @@ -37,17 +37,17 @@ using namespace lld; using namespace lld::elf; -const TargetInfo *elf::Target; +const TargetInfo *elf::target; -std::string lld::toString(RelType Type) { - StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type); - if (S == "Unknown") - return ("Unknown (" + Twine(Type) + ")").str(); - return S; +std::string lld::toString(RelType type) { + StringRef s = getELFRelocationTypeName(elf::config->emachine, type); + if (s == "Unknown") + return ("Unknown (" + Twine(type) + ")").str(); + return s; } TargetInfo *elf::getTarget() { - switch (Config->EMachine) { + switch (config->emachine) { case EM_386: case EM_IAMCU: return getX86TargetInfo(); @@ -62,7 +62,7 @@ case EM_HEXAGON: return getHexagonTargetInfo(); case EM_MIPS: - switch (Config->EKind) { + switch (config->ekind) { case ELF32LEKind: return getMipsTargetInfo(); case ELF32BEKind: @@ -90,29 +90,29 @@ llvm_unreachable("unknown target machine"); } -template static ErrorPlace getErrPlace(const uint8_t *Loc) { - for (InputSectionBase *D : InputSections) { - auto *IS = cast(D); - if (!IS->getParent()) +template static ErrorPlace getErrPlace(const uint8_t *loc) { + for (InputSectionBase *d : inputSections) { + auto *isec = cast(d); + if (!isec->getParent()) continue; - uint8_t *ISLoc = Out::BufferStart + IS->getParent()->Offset + IS->OutSecOff; - if (ISLoc <= Loc && Loc < ISLoc + IS->getSize()) - return {IS, IS->template getLocation(Loc - ISLoc) + ": "}; + uint8_t *isecLoc = Out::bufferStart + isec->getParent()->offset + isec->outSecOff; + if (isecLoc <= loc && loc < isecLoc + isec->getSize()) + return {isec, isec->template getLocation(loc - isecLoc) + ": "}; } return {}; } -ErrorPlace elf::getErrorPlace(const uint8_t *Loc) { - switch (Config->EKind) { +ErrorPlace elf::getErrorPlace(const uint8_t *loc) { + switch (config->ekind) { case ELF32LEKind: - return getErrPlace(Loc); + return getErrPlace(loc); case ELF32BEKind: - return getErrPlace(Loc); + return getErrPlace(loc); case ELF64LEKind: - return getErrPlace(Loc); + return getErrPlace(loc); case ELF64BEKind: - return getErrPlace(Loc); + return getErrPlace(loc); default: llvm_unreachable("unknown ELF type"); } @@ -120,62 +120,62 @@ TargetInfo::~TargetInfo() {} -int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, RelType Type) const { +int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const { return 0; } -bool TargetInfo::usesOnlyLowPageBits(RelType Type) const { return false; } +bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; } -bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, - uint64_t BranchAddr, const Symbol &S) const { +bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file, + uint64_t branchAddr, const Symbol &s) const { return false; } -bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, - uint8_t StOther) const { +bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end, + uint8_t stOther) const { llvm_unreachable("Target doesn't support split stacks."); } -bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { +bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { return true; } -void TargetInfo::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { - writeGotPlt(Buf, S); +void TargetInfo::writeIgotPlt(uint8_t *buf, const Symbol &s) const { + writeGotPlt(buf, s); } -RelExpr TargetInfo::adjustRelaxExpr(RelType Type, const uint8_t *Data, - RelExpr Expr) const { - return Expr; +RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data, + RelExpr expr) const { + return expr; } -void TargetInfo::relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const { +void TargetInfo::relaxGot(uint8_t *loc, RelType type, uint64_t val) const { llvm_unreachable("Should not have claimed to be relaxable"); } -void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, RelType Type, - uint64_t Val) const { +void TargetInfo::relaxTlsGdToLe(uint8_t *loc, RelType type, + uint64_t val) const { llvm_unreachable("Should not have claimed to be relaxable"); } -void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, RelType Type, - uint64_t Val) const { +void TargetInfo::relaxTlsGdToIe(uint8_t *loc, RelType type, + uint64_t val) const { llvm_unreachable("Should not have claimed to be relaxable"); } -void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, RelType Type, - uint64_t Val) const { +void TargetInfo::relaxTlsIeToLe(uint8_t *loc, RelType type, + uint64_t val) const { llvm_unreachable("Should not have claimed to be relaxable"); } -void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, RelType Type, - uint64_t Val) const { +void TargetInfo::relaxTlsLdToLe(uint8_t *loc, RelType type, + uint64_t val) const { llvm_unreachable("Should not have claimed to be relaxable"); } uint64_t TargetInfo::getImageBase() const { // Use -image-base if set. Fall back to the target default if not. - if (Config->ImageBase) - return *Config->ImageBase; - return Config->Pic ? 0 : DefaultImageBase; + if (config->imageBase) + return *config->imageBase; + return config->isPic ? 0 : defaultImageBase; } Index: lld/trunk/ELF/Thunks.h =================================================================== --- lld/trunk/ELF/Thunks.h +++ lld/trunk/ELF/Thunks.h @@ -27,20 +27,20 @@ // Thunks are assigned to synthetic ThunkSections class Thunk { public: - Thunk(Symbol &Destination); + Thunk(Symbol &destination); virtual ~Thunk(); virtual uint32_t size() = 0; - virtual void writeTo(uint8_t *Buf) = 0; + virtual void writeTo(uint8_t *buf) = 0; // All Thunks must define at least one symbol, known as the thunk target // symbol, so that we can redirect relocations to it. The thunk may define // additional symbols, but these are never targets for relocations. - virtual void addSymbols(ThunkSection &IS) = 0; + virtual void addSymbols(ThunkSection &isec) = 0; - void setOffset(uint64_t Offset); - Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value, - InputSectionBase &Section); + void setOffset(uint64_t offset); + Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, + InputSectionBase §ion); // Some Thunks must be placed immediately before their Target as they elide // a branch and fall through to the first Symbol in the Target. @@ -53,19 +53,19 @@ return true; } - Defined *getThunkTargetSym() const { return Syms[0]; } + Defined *getThunkTargetSym() const { return syms[0]; } // The alignment requirement for this Thunk, defaults to the size of the // typical code section alignment. - Symbol &Destination; - llvm::SmallVector Syms; - uint64_t Offset = 0; - uint32_t Alignment = 4; + Symbol &destination; + llvm::SmallVector syms; + uint64_t offset = 0; + uint32_t alignment = 4; }; // For a Relocation to symbol S create a Thunk to be added to a synthetic // ThunkSection. -Thunk *addThunk(const InputSection &IS, Relocation &Rel); +Thunk *addThunk(const InputSection &isec, Relocation &rel); } // namespace elf } // namespace lld Index: lld/trunk/ELF/Thunks.cpp =================================================================== --- lld/trunk/ELF/Thunks.cpp +++ lld/trunk/ELF/Thunks.cpp @@ -49,18 +49,18 @@ // AArch64 long range Thunks class AArch64ABSLongThunk final : public Thunk { public: - AArch64ABSLongThunk(Symbol &Dest) : Thunk(Dest) {} + AArch64ABSLongThunk(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 16; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; class AArch64ADRPThunk final : public Thunk { public: - AArch64ADRPThunk(Symbol &Dest) : Thunk(Dest) {} + AArch64ADRPThunk(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 12; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; // Base class for ARM thunks. @@ -73,19 +73,19 @@ // if the target is in range, otherwise it creates a long thunk. class ARMThunk : public Thunk { public: - ARMThunk(Symbol &Dest) : Thunk(Dest) {} + ARMThunk(Symbol &dest) : Thunk(dest) {} bool getMayUseShortThunk(); uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); } - void writeTo(uint8_t *Buf) override; - bool isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const override; + void writeTo(uint8_t *buf) override; + bool isCompatibleWith(const InputSection &isec, + const Relocation &rel) const override; // Returns the size of a long thunk. virtual uint32_t sizeLong() = 0; // Writes a long thunk to Buf. - virtual void writeLong(uint8_t *Buf) = 0; + virtual void writeLong(uint8_t *buf) = 0; private: // This field tracks whether all previously considered layouts would allow @@ -94,7 +94,7 @@ // distance to the target. We do this because transitioning from long to short // can create layout oscillations in certain corner cases which would prevent // the layout from converging. - bool MayUseShortThunk = true; + bool mayUseShortThunk = true; }; // Base class for Thumb-2 thunks. @@ -103,61 +103,61 @@ // which has a range of 16MB. class ThumbThunk : public Thunk { public: - ThumbThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; } + ThumbThunk(Symbol &dest) : Thunk(dest) { alignment = 2; } bool getMayUseShortThunk(); uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); } - void writeTo(uint8_t *Buf) override; - bool isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const override; + void writeTo(uint8_t *buf) override; + bool isCompatibleWith(const InputSection &isec, + const Relocation &rel) const override; // Returns the size of a long thunk. virtual uint32_t sizeLong() = 0; // Writes a long thunk to Buf. - virtual void writeLong(uint8_t *Buf) = 0; + virtual void writeLong(uint8_t *buf) = 0; private: // See comment in ARMThunk above. - bool MayUseShortThunk = true; + bool mayUseShortThunk = true; }; // Specific ARM Thunk implementations. The naming convention is: // Source State, TargetState, Target Requirement, ABS or PI, Range class ARMV7ABSLongThunk final : public ARMThunk { public: - ARMV7ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {} + ARMV7ABSLongThunk(Symbol &dest) : ARMThunk(dest) {} uint32_t sizeLong() override { return 12; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; class ARMV7PILongThunk final : public ARMThunk { public: - ARMV7PILongThunk(Symbol &Dest) : ARMThunk(Dest) {} + ARMV7PILongThunk(Symbol &dest) : ARMThunk(dest) {} uint32_t sizeLong() override { return 16; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; class ThumbV7ABSLongThunk final : public ThumbThunk { public: - ThumbV7ABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {} + ThumbV7ABSLongThunk(Symbol &dest) : ThumbThunk(dest) {} uint32_t sizeLong() override { return 10; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; class ThumbV7PILongThunk final : public ThumbThunk { public: - ThumbV7PILongThunk(Symbol &Dest) : ThumbThunk(Dest) {} + ThumbV7PILongThunk(Symbol &dest) : ThumbThunk(dest) {} uint32_t sizeLong() override { return 12; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; // Implementations of Thunks for older Arm architectures that do not support @@ -167,95 +167,95 @@ // can result in a thunk class ARMV5ABSLongThunk final : public ARMThunk { public: - ARMV5ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {} + ARMV5ABSLongThunk(Symbol &dest) : ARMThunk(dest) {} uint32_t sizeLong() override { return 8; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; - bool isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; + bool isCompatibleWith(const InputSection &isec, + const Relocation &rel) const override; }; class ARMV5PILongThunk final : public ARMThunk { public: - ARMV5PILongThunk(Symbol &Dest) : ARMThunk(Dest) {} + ARMV5PILongThunk(Symbol &dest) : ARMThunk(dest) {} uint32_t sizeLong() override { return 16; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; - bool isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; + bool isCompatibleWith(const InputSection &isec, + const Relocation &rel) const override; }; // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted class ThumbV6MABSLongThunk final : public ThumbThunk { public: - ThumbV6MABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {} + ThumbV6MABSLongThunk(Symbol &dest) : ThumbThunk(dest) {} uint32_t sizeLong() override { return 12; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; class ThumbV6MPILongThunk final : public ThumbThunk { public: - ThumbV6MPILongThunk(Symbol &Dest) : ThumbThunk(Dest) {} + ThumbV6MPILongThunk(Symbol &dest) : ThumbThunk(dest) {} uint32_t sizeLong() override { return 16; } - void writeLong(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeLong(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; // MIPS LA25 thunk class MipsThunk final : public Thunk { public: - MipsThunk(Symbol &Dest) : Thunk(Dest) {} + MipsThunk(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 16; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; InputSection *getTargetInputSection() const override; }; // microMIPS R2-R5 LA25 thunk class MicroMipsThunk final : public Thunk { public: - MicroMipsThunk(Symbol &Dest) : Thunk(Dest) {} + MicroMipsThunk(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 14; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; InputSection *getTargetInputSection() const override; }; // microMIPS R6 LA25 thunk class MicroMipsR6Thunk final : public Thunk { public: - MicroMipsR6Thunk(Symbol &Dest) : Thunk(Dest) {} + MicroMipsR6Thunk(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 12; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; InputSection *getTargetInputSection() const override; }; class PPC32PltCallStub final : public Thunk { public: - PPC32PltCallStub(const InputSection &IS, const Relocation &Rel, Symbol &Dest) - : Thunk(Dest), Addend(Rel.Type == R_PPC_PLTREL24 ? Rel.Addend : 0), - File(IS.File) {} + PPC32PltCallStub(const InputSection &isec, const Relocation &rel, Symbol &dest) + : Thunk(dest), addend(rel.type == R_PPC_PLTREL24 ? rel.addend : 0), + file(isec.file) {} uint32_t size() override { return 16; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; - bool isCompatibleWith(const InputSection &IS, const Relocation &Rel) const override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; + bool isCompatibleWith(const InputSection &isec, const Relocation &rel) const override; private: // For R_PPC_PLTREL24, this records the addend, which will be used to decide // the offsets in the call stub. - uint32_t Addend; + uint32_t addend; // Records the call site of the call stub. - const InputFile *File; + const InputFile *file; }; // PPC64 Plt call stubs. @@ -268,10 +268,10 @@ // 3) Transfering control to the target function through an indirect branch. class PPC64PltCallStub final : public Thunk { public: - PPC64PltCallStub(Symbol &Dest) : Thunk(Dest) {} + PPC64PltCallStub(Symbol &dest) : Thunk(dest) {} uint32_t size() override { return 20; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; }; // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte @@ -285,75 +285,75 @@ class PPC64LongBranchThunk : public Thunk { public: uint32_t size() override { return 16; } - void writeTo(uint8_t *Buf) override; - void addSymbols(ThunkSection &IS) override; + void writeTo(uint8_t *buf) override; + void addSymbols(ThunkSection &isec) override; protected: - PPC64LongBranchThunk(Symbol &Dest) : Thunk(Dest) {} + PPC64LongBranchThunk(Symbol &dest) : Thunk(dest) {} }; class PPC64PILongBranchThunk final : public PPC64LongBranchThunk { public: - PPC64PILongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) { - assert(!Dest.IsPreemptible); - if (Dest.isInPPC64Branchlt()) + PPC64PILongBranchThunk(Symbol &dest) : PPC64LongBranchThunk(dest) { + assert(!dest.isPreemptible); + if (dest.isInPPC64Branchlt()) return; - In.PPC64LongBranchTarget->addEntry(Dest); - Main->RelaDyn->addReloc( - {Target->RelativeRel, In.PPC64LongBranchTarget, - Dest.getPPC64LongBranchOffset(), true, &Dest, - getPPC64GlobalEntryToLocalEntryOffset(Dest.StOther)}); + in.ppc64LongBranchTarget->addEntry(dest); + mainPart->relaDyn->addReloc( + {target->relativeRel, in.ppc64LongBranchTarget, + dest.getPPC64LongBranchOffset(), true, &dest, + getPPC64GlobalEntryToLocalEntryOffset(dest.stOther)}); } }; class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk { public: - PPC64PDLongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) { - if (!Dest.isInPPC64Branchlt()) - In.PPC64LongBranchTarget->addEntry(Dest); + PPC64PDLongBranchThunk(Symbol &dest) : PPC64LongBranchThunk(dest) { + if (!dest.isInPPC64Branchlt()) + in.ppc64LongBranchTarget->addEntry(dest); } }; } // end anonymous namespace -Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value, - InputSectionBase &Section) { - Defined *D = addSyntheticLocal(Name, Type, Value, /*Size=*/0, Section); - Syms.push_back(D); - return D; +Defined *Thunk::addSymbol(StringRef name, uint8_t type, uint64_t value, + InputSectionBase §ion) { + Defined *d = addSyntheticLocal(name, type, value, /*Size=*/0, section); + syms.push_back(d); + return d; } -void Thunk::setOffset(uint64_t NewOffset) { - for (Defined *D : Syms) - D->Value = D->Value - Offset + NewOffset; - Offset = NewOffset; +void Thunk::setOffset(uint64_t newOffset) { + for (Defined *d : syms) + d->value = d->value - offset + newOffset; + offset = newOffset; } // AArch64 long range Thunks -static uint64_t getAArch64ThunkDestVA(const Symbol &S) { - uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA(); - return V; +static uint64_t getAArch64ThunkDestVA(const Symbol &s) { + uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA(); + return v; } -void AArch64ABSLongThunk::writeTo(uint8_t *Buf) { - const uint8_t Data[] = { +void AArch64ABSLongThunk::writeTo(uint8_t *buf) { + const uint8_t data[] = { 0x50, 0x00, 0x00, 0x58, // ldr x16, L0 0x00, 0x02, 0x1f, 0xd6, // br x16 0x00, 0x00, 0x00, 0x00, // L0: .xword S 0x00, 0x00, 0x00, 0x00, }; - uint64_t S = getAArch64ThunkDestVA(Destination); - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf + 8, R_AARCH64_ABS64, S); + uint64_t s = getAArch64ThunkDestVA(destination); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf + 8, R_AARCH64_ABS64, s); } -void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__AArch64AbsLongThunk_" + Destination.getName()), - STT_FUNC, 0, IS); - addSymbol("$x", STT_NOTYPE, 0, IS); - addSymbol("$d", STT_NOTYPE, 8, IS); +void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__AArch64AbsLongThunk_" + destination.getName()), + STT_FUNC, 0, isec); + addSymbol("$x", STT_NOTYPE, 0, isec); + addSymbol("$d", STT_NOTYPE, 8, isec); } // This Thunk has a maximum range of 4Gb, this is sufficient for all programs @@ -361,263 +361,263 @@ // clang and gcc do not support the large code model for position independent // code so it is safe to use this for position independent thunks without // worrying about the destination being more than 4Gb away. -void AArch64ADRPThunk::writeTo(uint8_t *Buf) { - const uint8_t Data[] = { +void AArch64ADRPThunk::writeTo(uint8_t *buf) { + const uint8_t data[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest) 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest) 0x00, 0x02, 0x1f, 0xd6, // br x16 }; - uint64_t S = getAArch64ThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA(); - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21, - getAArch64Page(S) - getAArch64Page(P)); - Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S); + uint64_t s = getAArch64ThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA(); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21, + getAArch64Page(s) - getAArch64Page(p)); + target->relocateOne(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s); } -void AArch64ADRPThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC, - 0, IS); - addSymbol("$x", STT_NOTYPE, 0, IS); +void AArch64ADRPThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC, + 0, isec); + addSymbol("$x", STT_NOTYPE, 0, isec); } // ARM Target Thunks -static uint64_t getARMThunkDestVA(const Symbol &S) { - uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA(); - return SignExtend64<32>(V); +static uint64_t getARMThunkDestVA(const Symbol &s) { + uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA(); + return SignExtend64<32>(v); } // This function returns true if the target is not Thumb and is within 2^26, and // it has not previously returned false (see comment for MayUseShortThunk). bool ARMThunk::getMayUseShortThunk() { - if (!MayUseShortThunk) + if (!mayUseShortThunk) return false; - uint64_t S = getARMThunkDestVA(Destination); - if (S & 1) { - MayUseShortThunk = false; + uint64_t s = getARMThunkDestVA(destination); + if (s & 1) { + mayUseShortThunk = false; return false; } - uint64_t P = getThunkTargetSym()->getVA(); - int64_t Offset = S - P - 8; - MayUseShortThunk = llvm::isInt<26>(Offset); - return MayUseShortThunk; + uint64_t p = getThunkTargetSym()->getVA(); + int64_t offset = s - p - 8; + mayUseShortThunk = llvm::isInt<26>(offset); + return mayUseShortThunk; } -void ARMThunk::writeTo(uint8_t *Buf) { +void ARMThunk::writeTo(uint8_t *buf) { if (!getMayUseShortThunk()) { - writeLong(Buf); + writeLong(buf); return; } - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA(); - int64_t Offset = S - P - 8; - const uint8_t Data[] = { + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA(); + int64_t offset = s - p - 8; + const uint8_t data[] = { 0x00, 0x00, 0x00, 0xea, // b S }; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_JUMP24, Offset); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_JUMP24, offset); } -bool ARMThunk::isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const { +bool ARMThunk::isCompatibleWith(const InputSection &isec, + const Relocation &rel) const { // Thumb branch relocations can't use BLX - return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24; + return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24; } // This function returns true if the target is Thumb and is within 2^25, and // it has not previously returned false (see comment for MayUseShortThunk). bool ThumbThunk::getMayUseShortThunk() { - if (!MayUseShortThunk) + if (!mayUseShortThunk) return false; - uint64_t S = getARMThunkDestVA(Destination); - if ((S & 1) == 0) { - MayUseShortThunk = false; + uint64_t s = getARMThunkDestVA(destination); + if ((s & 1) == 0) { + mayUseShortThunk = false; return false; } - uint64_t P = getThunkTargetSym()->getVA() & ~1; - int64_t Offset = S - P - 4; - MayUseShortThunk = llvm::isInt<25>(Offset); - return MayUseShortThunk; + uint64_t p = getThunkTargetSym()->getVA() & ~1; + int64_t offset = s - p - 4; + mayUseShortThunk = llvm::isInt<25>(offset); + return mayUseShortThunk; } -void ThumbThunk::writeTo(uint8_t *Buf) { +void ThumbThunk::writeTo(uint8_t *buf) { if (!getMayUseShortThunk()) { - writeLong(Buf); + writeLong(buf); return; } - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA(); - int64_t Offset = S - P - 4; - const uint8_t Data[] = { + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA(); + int64_t offset = s - p - 4; + const uint8_t data[] = { 0x00, 0xf0, 0x00, 0xb0, // b.w S }; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_THM_JUMP24, offset); } -bool ThumbThunk::isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const { +bool ThumbThunk::isCompatibleWith(const InputSection &isec, + const Relocation &rel) const { // ARM branch relocations can't use BLX - return Rel.Type != R_ARM_JUMP24 && Rel.Type != R_ARM_PC24 && Rel.Type != R_ARM_PLT32; + return rel.type != R_ARM_JUMP24 && rel.type != R_ARM_PC24 && rel.type != R_ARM_PLT32; } -void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ARMV7ABSLongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S 0x1c, 0xff, 0x2f, 0xe1, // bx ip }; - uint64_t S = getARMThunkDestVA(Destination); - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S); - Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S); + uint64_t s = getARMThunkDestVA(destination); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_MOVW_ABS_NC, s); + target->relocateOne(buf + 4, R_ARM_MOVT_ABS, s); } -void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()), - STT_FUNC, 0, IS); - addSymbol("$a", STT_NOTYPE, 0, IS); +void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__ARMv7ABSLongThunk_" + destination.getName()), + STT_FUNC, 0, isec); + addSymbol("$a", STT_NOTYPE, 0, isec); } -void ThumbV7ABSLongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S 0x60, 0x47, // bx ip }; - uint64_t S = getARMThunkDestVA(Destination); - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S); - Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S); + uint64_t s = getARMThunkDestVA(destination); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_THM_MOVW_ABS_NC, s); + target->relocateOne(buf + 4, R_ARM_THM_MOVT_ABS, s); } -void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()), - STT_FUNC, 1, IS); - addSymbol("$t", STT_NOTYPE, 0, IS); +void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + destination.getName()), + STT_FUNC, 1, isec); + addSymbol("$t", STT_NOTYPE, 0, isec); } -void ARMV7PILongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ARMV7PILongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8) 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8) 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc 0x1c, 0xff, 0x2f, 0xe1, // bx ip }; - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA(); - int64_t Offset = S - P - 16; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset); - Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, Offset); -} - -void ARMV7PILongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC, - 0, IS); - addSymbol("$a", STT_NOTYPE, 0, IS); + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA(); + int64_t offset = s - p - 16; + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_MOVW_PREL_NC, offset); + target->relocateOne(buf + 4, R_ARM_MOVT_PREL, offset); +} + +void ARMV7PILongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC, + 0, isec); + addSymbol("$a", STT_NOTYPE, 0, isec); } -void ThumbV7PILongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ThumbV7PILongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4) 0xfc, 0x44, // L1: add ip, pc 0x60, 0x47, // bx ip }; - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA() & ~0x1; - int64_t Offset = S - P - 12; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset); - Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, Offset); -} - -void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__ThumbV7PILongThunk_" + Destination.getName()), - STT_FUNC, 1, IS); - addSymbol("$t", STT_NOTYPE, 0, IS); + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + int64_t offset = s - p - 12; + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf, R_ARM_THM_MOVW_PREL_NC, offset); + target->relocateOne(buf + 4, R_ARM_THM_MOVT_PREL, offset); +} + +void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__ThumbV7PILongThunk_" + destination.getName()), + STT_FUNC, 1, isec); + addSymbol("$t", STT_NOTYPE, 0, isec); } -void ARMV5ABSLongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ARMV5ABSLongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1 0x00, 0x00, 0x00, 0x00, // L1: .word S }; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf + 4, R_ARM_ABS32, getARMThunkDestVA(Destination)); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination)); } -void ARMV5ABSLongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__ARMv5ABSLongThunk_" + Destination.getName()), - STT_FUNC, 0, IS); - addSymbol("$a", STT_NOTYPE, 0, IS); - addSymbol("$d", STT_NOTYPE, 4, IS); +void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__ARMv5ABSLongThunk_" + destination.getName()), + STT_FUNC, 0, isec); + addSymbol("$a", STT_NOTYPE, 0, isec); + addSymbol("$d", STT_NOTYPE, 4, isec); } -bool ARMV5ABSLongThunk::isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const { +bool ARMV5ABSLongThunk::isCompatibleWith(const InputSection &isec, + const Relocation &rel) const { // Thumb branch relocations can't use BLX - return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24; + return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24; } -void ARMV5PILongThunk::writeLong(uint8_t *Buf) { - const uint8_t Data[] = { +void ARMV5PILongThunk::writeLong(uint8_t *buf) { + const uint8_t data[] = { 0x04, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc,#4] ; L2 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip 0x1c, 0xff, 0x2f, 0xe1, // bx ip 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8) }; - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA() & ~0x1; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12); + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12); } -void ARMV5PILongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__ARMV5PILongThunk_" + Destination.getName()), STT_FUNC, - 0, IS); - addSymbol("$a", STT_NOTYPE, 0, IS); - addSymbol("$d", STT_NOTYPE, 12, IS); +void ARMV5PILongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC, + 0, isec); + addSymbol("$a", STT_NOTYPE, 0, isec); + addSymbol("$d", STT_NOTYPE, 12, isec); } -bool ARMV5PILongThunk::isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const { +bool ARMV5PILongThunk::isCompatibleWith(const InputSection &isec, + const Relocation &rel) const { // Thumb branch relocations can't use BLX - return Rel.Type != R_ARM_THM_JUMP19 && Rel.Type != R_ARM_THM_JUMP24; + return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24; } -void ThumbV6MABSLongThunk::writeLong(uint8_t *Buf) { +void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) { // Most Thumb instructions cannot access the high registers r8 - r15. As the // only register we can corrupt is r12 we must instead spill a low register // to the stack to use as a scratch register. We push r1 even though we // don't need to get some space to use for the return address. - const uint8_t Data[] = { + const uint8_t data[] = { 0x03, 0xb4, // push {r0, r1} ; Obtain scratch registers 0x01, 0x48, // ldr r0, [pc, #4] ; L1 0x01, 0x90, // str r0, [sp, #4] ; SP + 4 = S 0x01, 0xbd, // pop {r0, pc} ; restore r0 and branch to dest 0x00, 0x00, 0x00, 0x00 // L1: .word S }; - uint64_t S = getARMThunkDestVA(Destination); - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf + 8, R_ARM_ABS32, S); + uint64_t s = getARMThunkDestVA(destination); + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf + 8, R_ARM_ABS32, s); } -void ThumbV6MABSLongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__Thumbv6MABSLongThunk_" + Destination.getName()), - STT_FUNC, 1, IS); - addSymbol("$t", STT_NOTYPE, 0, IS); - addSymbol("$d", STT_NOTYPE, 8, IS); +void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__Thumbv6MABSLongThunk_" + destination.getName()), + STT_FUNC, 1, isec); + addSymbol("$t", STT_NOTYPE, 0, isec); + addSymbol("$d", STT_NOTYPE, 8, isec); } -void ThumbV6MPILongThunk::writeLong(uint8_t *Buf) { +void ThumbV6MPILongThunk::writeLong(uint8_t *buf) { // Most Thumb instructions cannot access the high registers r8 - r15. As the // only register we can corrupt is ip (r12) we must instead spill a low // register to the stack to use as a scratch register. - const uint8_t Data[] = { + const uint8_t data[] = { 0x01, 0xb4, // P: push {r0} ; Obtain scratch register 0x02, 0x48, // ldr r0, [pc, #8] ; L2 0x84, 0x46, // mov ip, r0 ; high to low register @@ -626,185 +626,185 @@ 0xc0, 0x46, // nop ; pad to 4-byte boundary 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4) }; - uint64_t S = getARMThunkDestVA(Destination); - uint64_t P = getThunkTargetSym()->getVA() & ~0x1; - memcpy(Buf, Data, sizeof(Data)); - Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12); + uint64_t s = getARMThunkDestVA(destination); + uint64_t p = getThunkTargetSym()->getVA() & ~0x1; + memcpy(buf, data, sizeof(data)); + target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12); } -void ThumbV6MPILongThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__Thumbv6MPILongThunk_" + Destination.getName()), - STT_FUNC, 1, IS); - addSymbol("$t", STT_NOTYPE, 0, IS); - addSymbol("$d", STT_NOTYPE, 12, IS); +void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__Thumbv6MPILongThunk_" + destination.getName()), + STT_FUNC, 1, isec); + addSymbol("$t", STT_NOTYPE, 0, isec); + addSymbol("$d", STT_NOTYPE, 12, isec); } // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. -void MipsThunk::writeTo(uint8_t *Buf) { - uint64_t S = Destination.getVA(); - write32(Buf, 0x3c190000); // lui $25, %hi(func) - write32(Buf + 4, 0x08000000 | (S >> 2)); // j func - write32(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func) - write32(Buf + 12, 0x00000000); // nop - Target->relocateOne(Buf, R_MIPS_HI16, S); - Target->relocateOne(Buf + 8, R_MIPS_LO16, S); +void MipsThunk::writeTo(uint8_t *buf) { + uint64_t s = destination.getVA(); + write32(buf, 0x3c190000); // lui $25, %hi(func) + write32(buf + 4, 0x08000000 | (s >> 2)); // j func + write32(buf + 8, 0x27390000); // addiu $25, $25, %lo(func) + write32(buf + 12, 0x00000000); // nop + target->relocateOne(buf, R_MIPS_HI16, s); + target->relocateOne(buf + 8, R_MIPS_LO16, s); } -void MipsThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__LA25Thunk_" + Destination.getName()), STT_FUNC, 0, - IS); +void MipsThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0, + isec); } InputSection *MipsThunk::getTargetInputSection() const { - auto &DR = cast(Destination); - return dyn_cast(DR.Section); + auto &dr = cast(destination); + return dyn_cast(dr.section); } // Write microMIPS R2-R5 LA25 thunk code // to call PIC function from the non-PIC one. -void MicroMipsThunk::writeTo(uint8_t *Buf) { - uint64_t S = Destination.getVA(); - write16(Buf, 0x41b9); // lui $25, %hi(func) - write16(Buf + 4, 0xd400); // j func - write16(Buf + 8, 0x3339); // addiu $25, $25, %lo(func) - write16(Buf + 12, 0x0c00); // nop - Target->relocateOne(Buf, R_MICROMIPS_HI16, S); - Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S); - Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S); +void MicroMipsThunk::writeTo(uint8_t *buf) { + uint64_t s = destination.getVA(); + write16(buf, 0x41b9); // lui $25, %hi(func) + write16(buf + 4, 0xd400); // j func + write16(buf + 8, 0x3339); // addiu $25, $25, %lo(func) + write16(buf + 12, 0x0c00); // nop + target->relocateOne(buf, R_MICROMIPS_HI16, s); + target->relocateOne(buf + 4, R_MICROMIPS_26_S1, s); + target->relocateOne(buf + 8, R_MICROMIPS_LO16, s); } -void MicroMipsThunk::addSymbols(ThunkSection &IS) { - Defined *D = addSymbol( - Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS); - D->StOther |= STO_MIPS_MICROMIPS; +void MicroMipsThunk::addSymbols(ThunkSection &isec) { + Defined *d = addSymbol( + Saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); + d->stOther |= STO_MIPS_MICROMIPS; } InputSection *MicroMipsThunk::getTargetInputSection() const { - auto &DR = cast(Destination); - return dyn_cast(DR.Section); + auto &dr = cast(destination); + return dyn_cast(dr.section); } // Write microMIPS R6 LA25 thunk code // to call PIC function from the non-PIC one. -void MicroMipsR6Thunk::writeTo(uint8_t *Buf) { - uint64_t S = Destination.getVA(); - uint64_t P = getThunkTargetSym()->getVA(); - write16(Buf, 0x1320); // lui $25, %hi(func) - write16(Buf + 4, 0x3339); // addiu $25, $25, %lo(func) - write16(Buf + 8, 0x9400); // bc func - Target->relocateOne(Buf, R_MICROMIPS_HI16, S); - Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S); - Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12); +void MicroMipsR6Thunk::writeTo(uint8_t *buf) { + uint64_t s = destination.getVA(); + uint64_t p = getThunkTargetSym()->getVA(); + write16(buf, 0x1320); // lui $25, %hi(func) + write16(buf + 4, 0x3339); // addiu $25, $25, %lo(func) + write16(buf + 8, 0x9400); // bc func + target->relocateOne(buf, R_MICROMIPS_HI16, s); + target->relocateOne(buf + 4, R_MICROMIPS_LO16, s); + target->relocateOne(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12); } -void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) { - Defined *D = addSymbol( - Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS); - D->StOther |= STO_MIPS_MICROMIPS; +void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) { + Defined *d = addSymbol( + Saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec); + d->stOther |= STO_MIPS_MICROMIPS; } InputSection *MicroMipsR6Thunk::getTargetInputSection() const { - auto &DR = cast(Destination); - return dyn_cast(DR.Section); + auto &dr = cast(destination); + return dyn_cast(dr.section); } -void PPC32PltCallStub::writeTo(uint8_t *Buf) { - if (!Config->Pic) { - uint64_t VA = Destination.getGotPltVA(); - write32(Buf + 0, 0x3d600000 | (VA + 0x8000) >> 16); // lis r11,ha - write32(Buf + 4, 0x816b0000 | (uint16_t)VA); // lwz r11,l(r11) - write32(Buf + 8, 0x7d6903a6); // mtctr r11 - write32(Buf + 12, 0x4e800420); // bctr +void PPC32PltCallStub::writeTo(uint8_t *buf) { + if (!config->isPic) { + uint64_t va = destination.getGotPltVA(); + write32(buf + 0, 0x3d600000 | (va + 0x8000) >> 16); // lis r11,ha + write32(buf + 4, 0x816b0000 | (uint16_t)va); // lwz r11,l(r11) + write32(buf + 8, 0x7d6903a6); // mtctr r11 + write32(buf + 12, 0x4e800420); // bctr return; } - uint32_t Offset; - if (Addend >= 0x8000) { + uint32_t offset; + if (addend >= 0x8000) { // The stub loads an address relative to r30 (.got2+Addend). Addend is // almost always 0x8000. The address of .got2 is different in another object // file, so a stub cannot be shared. - Offset = Destination.getGotPltVA() - (In.PPC32Got2->getParent()->getVA() + - File->PPC32Got2OutSecOff + Addend); + offset = destination.getGotPltVA() - (in.ppc32Got2->getParent()->getVA() + + file->ppc32Got2OutSecOff + addend); } else { // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is // currently the address of .got). - Offset = Destination.getGotPltVA() - In.Got->getVA(); + offset = destination.getGotPltVA() - in.got->getVA(); } - uint16_t HA = (Offset + 0x8000) >> 16, L = (uint16_t)Offset; - if (HA == 0) { - write32(Buf + 0, 0x817e0000 | L); // lwz r11,l(r30) - write32(Buf + 4, 0x7d6903a6); // mtctr r11 - write32(Buf + 8, 0x4e800420); // bctr - write32(Buf + 12, 0x60000000); // nop + uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset; + if (ha == 0) { + write32(buf + 0, 0x817e0000 | l); // lwz r11,l(r30) + write32(buf + 4, 0x7d6903a6); // mtctr r11 + write32(buf + 8, 0x4e800420); // bctr + write32(buf + 12, 0x60000000); // nop } else { - write32(Buf + 0, 0x3d7e0000 | HA); // addis r11,r30,ha - write32(Buf + 4, 0x816b0000 | L); // lwz r11,l(r11) - write32(Buf + 8, 0x7d6903a6); // mtctr r11 - write32(Buf + 12, 0x4e800420); // bctr + write32(buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha + write32(buf + 4, 0x816b0000 | l); // lwz r11,l(r11) + write32(buf + 8, 0x7d6903a6); // mtctr r11 + write32(buf + 12, 0x4e800420); // bctr } } -void PPC32PltCallStub::addSymbols(ThunkSection &IS) { - std::string Buf; - raw_string_ostream OS(Buf); - OS << format_hex_no_prefix(Addend, 8); - if (!Config->Pic) - OS << ".plt_call32."; - else if (Addend >= 0x8000) - OS << ".got2.plt_pic32."; +void PPC32PltCallStub::addSymbols(ThunkSection &isec) { + std::string buf; + raw_string_ostream os(buf); + os << format_hex_no_prefix(addend, 8); + if (!config->isPic) + os << ".plt_call32."; + else if (addend >= 0x8000) + os << ".got2.plt_pic32."; else - OS << ".plt_pic32."; - OS << Destination.getName(); - addSymbol(Saver.save(OS.str()), STT_FUNC, 0, IS); + os << ".plt_pic32."; + os << destination.getName(); + addSymbol(Saver.save(os.str()), STT_FUNC, 0, isec); } -bool PPC32PltCallStub::isCompatibleWith(const InputSection &IS, - const Relocation &Rel) const { - return !Config->Pic || (IS.File == File && Rel.Addend == Addend); +bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec, + const Relocation &rel) const { + return !config->isPic || (isec.file == file && rel.addend == addend); } -static void writePPCLoadAndBranch(uint8_t *Buf, int64_t Offset) { - uint16_t OffHa = (Offset + 0x8000) >> 16; - uint16_t OffLo = Offset & 0xffff; +static void writePPCLoadAndBranch(uint8_t *buf, int64_t offset) { + uint16_t offHa = (offset + 0x8000) >> 16; + uint16_t offLo = offset & 0xffff; - write32(Buf + 0, 0x3d820000 | OffHa); // addis r12, r2, OffHa - write32(Buf + 4, 0xe98c0000 | OffLo); // ld r12, OffLo(r12) - write32(Buf + 8, 0x7d8903a6); // mtctr r12 - write32(Buf + 12, 0x4e800420); // bctr + write32(buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa + write32(buf + 4, 0xe98c0000 | offLo); // ld r12, OffLo(r12) + write32(buf + 8, 0x7d8903a6); // mtctr r12 + write32(buf + 12, 0x4e800420); // bctr } -void PPC64PltCallStub::writeTo(uint8_t *Buf) { - int64_t Offset = Destination.getGotPltVA() - getPPC64TocBase(); +void PPC64PltCallStub::writeTo(uint8_t *buf) { + int64_t offset = destination.getGotPltVA() - getPPC64TocBase(); // Save the TOC pointer to the save-slot reserved in the call frame. - write32(Buf + 0, 0xf8410018); // std r2,24(r1) - writePPCLoadAndBranch(Buf + 4, Offset); + write32(buf + 0, 0xf8410018); // std r2,24(r1) + writePPCLoadAndBranch(buf + 4, offset); } -void PPC64PltCallStub::addSymbols(ThunkSection &IS) { - Defined *S = addSymbol(Saver.save("__plt_" + Destination.getName()), STT_FUNC, - 0, IS); - S->NeedsTocRestore = true; +void PPC64PltCallStub::addSymbols(ThunkSection &isec) { + Defined *s = addSymbol(Saver.save("__plt_" + destination.getName()), STT_FUNC, + 0, isec); + s->needsTocRestore = true; } -void PPC64LongBranchThunk::writeTo(uint8_t *Buf) { - int64_t Offset = Destination.getPPC64LongBranchTableVA() - getPPC64TocBase(); - writePPCLoadAndBranch(Buf, Offset); +void PPC64LongBranchThunk::writeTo(uint8_t *buf) { + int64_t offset = destination.getPPC64LongBranchTableVA() - getPPC64TocBase(); + writePPCLoadAndBranch(buf, offset); } -void PPC64LongBranchThunk::addSymbols(ThunkSection &IS) { - addSymbol(Saver.save("__long_branch_" + Destination.getName()), STT_FUNC, 0, - IS); +void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) { + addSymbol(Saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0, + isec); } -Thunk::Thunk(Symbol &D) : Destination(D), Offset(0) {} +Thunk::Thunk(Symbol &d) : destination(d), offset(0) {} Thunk::~Thunk() = default; -static Thunk *addThunkAArch64(RelType Type, Symbol &S) { - if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) +static Thunk *addThunkAArch64(RelType type, Symbol &s) { + if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26) fatal("unrecognized relocation type"); - if (Config->PicThunk) - return make(S); - return make(S); + if (config->picThunk) + return make(s); + return make(s); } // Creates a thunk for Thumb-ARM interworking. @@ -812,18 +812,18 @@ // - MOVT and MOVW instructions cannot be used // - Only Thumb relocation that can generate a Thunk is a BL, this can always // be transformed into a BLX -static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) { - switch (Reloc) { +static Thunk *addThunkPreArmv7(RelType reloc, Symbol &s) { + switch (reloc) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: case R_ARM_THM_CALL: - if (Config->PicThunk) - return make(S); - return make(S); + if (config->picThunk) + return make(s); + return make(s); } - fatal("relocation " + toString(Reloc) + " to " + toString(S) + + fatal("relocation " + toString(reloc) + " to " + toString(s) + " not supported for Armv5 or Armv6 targets"); } @@ -832,21 +832,21 @@ // - MOVT and MOVW instructions cannot be used. // - Only a limited number of instructions can access registers r8 and above // - No interworking support is needed (all Thumb). -static Thunk *addThunkV6M(RelType Reloc, Symbol &S) { - switch (Reloc) { +static Thunk *addThunkV6M(RelType reloc, Symbol &s) { + switch (reloc) { case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - if (Config->Pic) - return make(S); - return make(S); + if (config->isPic) + return make(s); + return make(s); } - fatal("relocation " + toString(Reloc) + " to " + toString(S) + + fatal("relocation " + toString(reloc) + " to " + toString(s) + " not supported for Armv6-M targets"); } // Creates a thunk for Thumb-ARM interworking or branch range extension. -static Thunk *addThunkArm(RelType Reloc, Symbol &S) { +static Thunk *addThunkArm(RelType reloc, Symbol &s) { // Decide which Thunk is needed based on: // Available instruction set // - An Arm Thunk can only be used if Arm state is available. @@ -863,72 +863,72 @@ // can use in Thunks. The flags below are set by reading the BuildAttributes // of the input objects. InputFiles.cpp contains the mapping from ARM // architecture to flag. - if (!Config->ARMHasMovtMovw) { - if (!Config->ARMJ1J2BranchEncoding) - return addThunkPreArmv7(Reloc, S); - return addThunkV6M(Reloc, S); + if (!config->armHasMovtMovw) { + if (!config->armJ1J2BranchEncoding) + return addThunkPreArmv7(reloc, s); + return addThunkV6M(reloc, s); } - switch (Reloc) { + switch (reloc) { case R_ARM_PC24: case R_ARM_PLT32: case R_ARM_JUMP24: case R_ARM_CALL: - if (Config->PicThunk) - return make(S); - return make(S); + if (config->picThunk) + return make(s); + return make(s); case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP24: case R_ARM_THM_CALL: - if (Config->PicThunk) - return make(S); - return make(S); + if (config->picThunk) + return make(s); + return make(s); } fatal("unrecognized relocation type"); } -static Thunk *addThunkMips(RelType Type, Symbol &S) { - if ((S.StOther & STO_MIPS_MICROMIPS) && isMipsR6()) - return make(S); - if (S.StOther & STO_MIPS_MICROMIPS) - return make(S); - return make(S); +static Thunk *addThunkMips(RelType type, Symbol &s) { + if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6()) + return make(s); + if (s.stOther & STO_MIPS_MICROMIPS) + return make(s); + return make(s); } -static Thunk *addThunkPPC32(const InputSection &IS, const Relocation &Rel, Symbol &S) { - assert((Rel.Type == R_PPC_REL24 || Rel.Type == R_PPC_PLTREL24) && +static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel, Symbol &s) { + assert((rel.type == R_PPC_REL24 || rel.type == R_PPC_PLTREL24) && "unexpected relocation type for thunk"); - return make(IS, Rel, S); + return make(isec, rel, s); } -static Thunk *addThunkPPC64(RelType Type, Symbol &S) { - assert(Type == R_PPC64_REL24 && "unexpected relocation type for thunk"); - if (S.isInPlt()) - return make(S); +static Thunk *addThunkPPC64(RelType type, Symbol &s) { + assert(type == R_PPC64_REL24 && "unexpected relocation type for thunk"); + if (s.isInPlt()) + return make(s); - if (Config->PicThunk) - return make(S); + if (config->picThunk) + return make(s); - return make(S); + return make(s); } -Thunk *addThunk(const InputSection &IS, Relocation &Rel) { - Symbol &S = *Rel.Sym; +Thunk *addThunk(const InputSection &isec, Relocation &rel) { + Symbol &s = *rel.sym; - if (Config->EMachine == EM_AARCH64) - return addThunkAArch64(Rel.Type, S); + if (config->emachine == EM_AARCH64) + return addThunkAArch64(rel.type, s); - if (Config->EMachine == EM_ARM) - return addThunkArm(Rel.Type, S); + if (config->emachine == EM_ARM) + return addThunkArm(rel.type, s); - if (Config->EMachine == EM_MIPS) - return addThunkMips(Rel.Type, S); + if (config->emachine == EM_MIPS) + return addThunkMips(rel.type, s); - if (Config->EMachine == EM_PPC) - return addThunkPPC32(IS, Rel, S); + if (config->emachine == EM_PPC) + return addThunkPPC32(isec, rel, s); - if (Config->EMachine == EM_PPC64) - return addThunkPPC64(Rel.Type, S); + if (config->emachine == EM_PPC64) + return addThunkPPC64(rel.type, s); llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC"); } Index: lld/trunk/ELF/Writer.h =================================================================== --- lld/trunk/ELF/Writer.h +++ lld/trunk/ELF/Writer.h @@ -25,8 +25,8 @@ // Each contains type, access flags and range of output sections that will be // placed in it. struct PhdrEntry { - PhdrEntry(unsigned Type, unsigned Flags) : p_type(Type), p_flags(Flags) {} - void add(OutputSection *Sec); + PhdrEntry(unsigned type, unsigned flags) : p_type(type), p_flags(flags) {} + void add(OutputSection *sec); uint64_t p_paddr = 0; uint64_t p_vaddr = 0; @@ -37,22 +37,22 @@ uint32_t p_type = 0; uint32_t p_flags = 0; - OutputSection *FirstSec = nullptr; - OutputSection *LastSec = nullptr; - bool HasLMA = false; + OutputSection *firstSec = nullptr; + OutputSection *lastSec = nullptr; + bool hasLMA = false; - uint64_t LMAOffset = 0; + uint64_t lmaOffset = 0; }; void addReservedSymbols(); -llvm::StringRef getOutputSectionName(const InputSectionBase *S); +llvm::StringRef getOutputSectionName(const InputSectionBase *s); template uint32_t calcMipsEFlags(); -uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, - llvm::StringRef FileName); +uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag, + llvm::StringRef fileName); -bool isMipsN32Abi(const InputFile *F); +bool isMipsN32Abi(const InputFile *f); bool isMicroMips(); bool isMipsR6(); } // namespace elf Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -42,7 +42,7 @@ // The writer writes a SymbolTable result to a file. template class Writer { public: - Writer() : Buffer(errorHandler().OutputBuffer) {} + Writer() : buffer(errorHandler().OutputBuffer) {} using Elf_Shdr = typename ELFT::Shdr; using Elf_Ehdr = typename ELFT::Ehdr; using Elf_Phdr = typename ELFT::Phdr; @@ -52,7 +52,7 @@ private: void copyLocalSymbols(); void addSectionSymbols(); - void forEachRelSec(llvm::function_ref Fn); + void forEachRelSec(llvm::function_ref fn); void sortSections(); void resolveShfLinkOrder(); void finalizeAddressDependentContent(); @@ -61,13 +61,13 @@ void checkExecuteOnly(); void setReservedSymbolSections(); - std::vector createPhdrs(Partition &Part); - void removeEmptyPTLoad(std::vector &PhdrEntry); - void addPhdrForSection(Partition &Part, unsigned ShType, unsigned PType, - unsigned PFlags); + std::vector createPhdrs(Partition &part); + void removeEmptyPTLoad(std::vector &phdrEntry); + void addPhdrForSection(Partition &part, unsigned shType, unsigned pType, + unsigned pFlags); void assignFileOffsets(); void assignFileOffsetsBinary(); - void setPhdrs(Partition &Part); + void setPhdrs(Partition &part); void checkSections(); void fixSectionAlignments(); void openFile(); @@ -77,34 +77,34 @@ void writeSectionsBinary(); void writeBuildId(); - std::unique_ptr &Buffer; + std::unique_ptr &buffer; void addRelIpltSymbols(); void addStartEndSymbols(); - void addStartStopSymbols(OutputSection *Sec); + void addStartStopSymbols(OutputSection *sec); - uint64_t FileSize; - uint64_t SectionHeaderOff; + uint64_t fileSize; + uint64_t sectionHeaderOff; }; } // anonymous namespace -static bool isSectionPrefix(StringRef Prefix, StringRef Name) { - return Name.startswith(Prefix) || Name == Prefix.drop_back(); +static bool isSectionPrefix(StringRef prefix, StringRef name) { + return name.startswith(prefix) || name == prefix.drop_back(); } -StringRef elf::getOutputSectionName(const InputSectionBase *S) { - if (Config->Relocatable) - return S->Name; +StringRef elf::getOutputSectionName(const InputSectionBase *s) { + if (config->relocatable) + return s->name; // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want // to emit .rela.text.foo as .rela.text.bar for consistency (this is not // technically required, but not doing it is odd). This code guarantees that. - if (auto *IS = dyn_cast(S)) { - if (InputSectionBase *Rel = IS->getRelocatedSection()) { - OutputSection *Out = Rel->getOutputSection(); - if (S->Type == SHT_RELA) - return Saver.save(".rela" + Out->Name); - return Saver.save(".rel" + Out->Name); + if (auto *isec = dyn_cast(s)) { + if (InputSectionBase *rel = isec->getRelocatedSection()) { + OutputSection *out = rel->getOutputSection(); + if (s->type == SHT_RELA) + return Saver.save(".rela" + out->name); + return Saver.save(".rel" + out->name); } } @@ -114,130 +114,130 @@ // When enabled, this allows identifying the hot code region (.text.hot) in // the final binary which can be selectively mapped to huge pages or mlocked, // for instance. - if (Config->ZKeepTextSectionPrefix) - for (StringRef V : + if (config->zKeepTextSectionPrefix) + for (StringRef v : {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) - if (isSectionPrefix(V, S->Name)) - return V.drop_back(); + if (isSectionPrefix(v, s->name)) + return v.drop_back(); - for (StringRef V : + for (StringRef v : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) - if (isSectionPrefix(V, S->Name)) - return V.drop_back(); + if (isSectionPrefix(v, s->name)) + return v.drop_back(); // CommonSection is identified as "COMMON" in linker scripts. // By default, it should go to .bss section. - if (S->Name == "COMMON") + if (s->name == "COMMON") return ".bss"; - return S->Name; + return s->name; } static bool needsInterpSection() { - return !SharedFiles.empty() && !Config->DynamicLinker.empty() && - Script->needsInterpSection(); + return !sharedFiles.empty() && !config->dynamicLinker.empty() && + script->needsInterpSection(); } template void elf::writeResult() { Writer().run(); } template -void Writer::removeEmptyPTLoad(std::vector &Phdrs) { - llvm::erase_if(Phdrs, [&](const PhdrEntry *P) { - if (P->p_type != PT_LOAD) +void Writer::removeEmptyPTLoad(std::vector &phdrs) { + llvm::erase_if(phdrs, [&](const PhdrEntry *p) { + if (p->p_type != PT_LOAD) return false; - if (!P->FirstSec) + if (!p->firstSec) return true; - uint64_t Size = P->LastSec->Addr + P->LastSec->Size - P->FirstSec->Addr; - return Size == 0; + uint64_t size = p->lastSec->addr + p->lastSec->size - p->firstSec->addr; + return size == 0; }); } template static void copySectionsIntoPartitions() { - std::vector NewSections; - for (unsigned Part = 2; Part != Partitions.size() + 1; ++Part) { - for (InputSectionBase *S : InputSections) { - if (!(S->Flags & SHF_ALLOC) || !S->isLive()) + std::vector newSections; + for (unsigned part = 2; part != partitions.size() + 1; ++part) { + for (InputSectionBase *s : inputSections) { + if (!(s->flags & SHF_ALLOC) || !s->isLive()) continue; - InputSectionBase *Copy; - if (S->Type == SHT_NOTE) - Copy = make(cast(*S)); - else if (auto *ES = dyn_cast(S)) - Copy = make(*ES); + InputSectionBase *copy; + if (s->type == SHT_NOTE) + copy = make(cast(*s)); + else if (auto *es = dyn_cast(s)) + copy = make(*es); else continue; - Copy->Partition = Part; - NewSections.push_back(Copy); + copy->partition = part; + newSections.push_back(copy); } } - InputSections.insert(InputSections.end(), NewSections.begin(), - NewSections.end()); + inputSections.insert(inputSections.end(), newSections.begin(), + newSections.end()); } template static void combineEhSections() { - for (InputSectionBase *&S : InputSections) { + for (InputSectionBase *&s : inputSections) { // Ignore dead sections and the partition end marker (.part.end), // whose partition number is out of bounds. - if (!S->isLive() || S->Partition == 255) + if (!s->isLive() || s->partition == 255) continue; - Partition &Part = S->getPartition(); - if (auto *ES = dyn_cast(S)) { - Part.EhFrame->addSection(ES); - S = nullptr; - } else if (S->kind() == SectionBase::Regular && Part.ARMExidx && - Part.ARMExidx->addSection(cast(S))) { - S = nullptr; + Partition &part = s->getPartition(); + if (auto *es = dyn_cast(s)) { + part.ehFrame->addSection(es); + s = nullptr; + } else if (s->kind() == SectionBase::Regular && part.armExidx && + part.armExidx->addSection(cast(s))) { + s = nullptr; } } - std::vector &V = InputSections; - V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); + std::vector &v = inputSections; + v.erase(std::remove(v.begin(), v.end(), nullptr), v.end()); } -static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, - uint64_t Val, uint8_t StOther = STV_HIDDEN, - uint8_t Binding = STB_GLOBAL) { - Symbol *S = Symtab->find(Name); - if (!S || S->isDefined()) +static Defined *addOptionalRegular(StringRef name, SectionBase *sec, + uint64_t val, uint8_t stOther = STV_HIDDEN, + uint8_t binding = STB_GLOBAL) { + Symbol *s = symtab->find(name); + if (!s || s->isDefined()) return nullptr; - S->resolve(Defined{/*File=*/nullptr, Name, Binding, StOther, STT_NOTYPE, Val, - /*Size=*/0, Sec}); - return cast(S); + s->resolve(Defined{/*File=*/nullptr, name, binding, stOther, STT_NOTYPE, val, + /*Size=*/0, sec}); + return cast(s); } -static Defined *addAbsolute(StringRef Name) { - Symbol *Sym = Symtab->addSymbol(Defined{nullptr, Name, STB_GLOBAL, STV_HIDDEN, +static Defined *addAbsolute(StringRef name) { + Symbol *sym = symtab->addSymbol(Defined{nullptr, name, STB_GLOBAL, STV_HIDDEN, STT_NOTYPE, 0, 0, nullptr}); - return cast(Sym); + return cast(sym); } // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. void elf::addReservedSymbols() { - if (Config->EMachine == EM_MIPS) { + if (config->emachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which by default is relative // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = addAbsolute("_gp"); + ElfSym::mipsGp = addAbsolute("_gp"); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. - if (Symtab->find("_gp_disp")) - ElfSym::MipsGpDisp = addAbsolute("_gp_disp"); + if (symtab->find("_gp_disp")) + ElfSym::mipsGpDisp = addAbsolute("_gp_disp"); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op // in case of using -mno-shared option. // https://sourceware.org/ml/binutils/2004-12/msg00094.html - if (Symtab->find("__gnu_local_gp")) - ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp"); - } else if (Config->EMachine == EM_PPC) { + if (symtab->find("__gnu_local_gp")) + ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp"); + } else if (config->emachine == EM_PPC) { // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't // support Small Data Area, define it arbitrarily as 0. addOptionalRegular("_SDA_BASE_", nullptr, 0, STV_HIDDEN); @@ -251,62 +251,62 @@ // the .got section. // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the // correctness of some relocations depends on its value. - StringRef GotSymName = - (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_"; + StringRef gotSymName = + (config->emachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_"; - if (Symbol *S = Symtab->find(GotSymName)) { - if (S->isDefined()) { - error(toString(S->File) + " cannot redefine linker defined symbol '" + - GotSymName + "'"); + if (Symbol *s = symtab->find(gotSymName)) { + if (s->isDefined()) { + error(toString(s->file) + " cannot redefine linker defined symbol '" + + gotSymName + "'"); return; } - uint64_t GotOff = 0; - if (Config->EMachine == EM_PPC64) - GotOff = 0x8000; - - S->resolve(Defined{/*File=*/nullptr, GotSymName, STB_GLOBAL, STV_HIDDEN, - STT_NOTYPE, GotOff, /*Size=*/0, Out::ElfHeader}); - ElfSym::GlobalOffsetTable = cast(S); + uint64_t gotOff = 0; + if (config->emachine == EM_PPC64) + gotOff = 0x8000; + + s->resolve(Defined{/*File=*/nullptr, gotSymName, STB_GLOBAL, STV_HIDDEN, + STT_NOTYPE, gotOff, /*Size=*/0, Out::elfHeader}); + ElfSym::globalOffsetTable = cast(s); } // __ehdr_start is the location of ELF file headers. Note that we define // this symbol unconditionally even when using a linker script, which // differs from the behavior implemented by GNU linker which only define // this symbol if ELF headers are in the memory mapped segment. - addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN); + addOptionalRegular("__ehdr_start", Out::elfHeader, 0, STV_HIDDEN); // __executable_start is not documented, but the expectation of at // least the Android libc is that it points to the ELF header. - addOptionalRegular("__executable_start", Out::ElfHeader, 0, STV_HIDDEN); + addOptionalRegular("__executable_start", Out::elfHeader, 0, STV_HIDDEN); // __dso_handle symbol is passed to cxa_finalize as a marker to identify // each DSO. The address of the symbol doesn't matter as long as they are // different in different DSOs, so we chose the start address of the DSO. - addOptionalRegular("__dso_handle", Out::ElfHeader, 0, STV_HIDDEN); + addOptionalRegular("__dso_handle", Out::elfHeader, 0, STV_HIDDEN); // If linker script do layout we do not need to create any standart symbols. - if (Script->HasSectionsCommand) + if (script->hasSectionsCommand) return; - auto Add = [](StringRef S, int64_t Pos) { - return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); + auto add = [](StringRef s, int64_t pos) { + return addOptionalRegular(s, Out::elfHeader, pos, STV_DEFAULT); }; - ElfSym::Bss = Add("__bss_start", 0); - ElfSym::End1 = Add("end", -1); - ElfSym::End2 = Add("_end", -1); - ElfSym::Etext1 = Add("etext", -1); - ElfSym::Etext2 = Add("_etext", -1); - ElfSym::Edata1 = Add("edata", -1); - ElfSym::Edata2 = Add("_edata", -1); + ElfSym::bss = add("__bss_start", 0); + ElfSym::end1 = add("end", -1); + ElfSym::end2 = add("_end", -1); + ElfSym::etext1 = add("etext", -1); + ElfSym::etext2 = add("_etext", -1); + ElfSym::edata1 = add("edata", -1); + ElfSym::edata2 = add("_edata", -1); } -static OutputSection *findSection(StringRef Name, unsigned Partition = 1) { - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - if (Sec->Name == Name && Sec->Partition == Partition) - return Sec; +static OutputSection *findSection(StringRef name, unsigned partition = 1) { + for (BaseCommand *base : script->sectionCommands) + if (auto *sec = dyn_cast(base)) + if (sec->name == name && sec->partition == partition) + return sec; return nullptr; } @@ -314,195 +314,195 @@ template static void createSyntheticSections() { // Initialize all pointers with NULL. This is needed because // you can call lld::elf::main more than once as a library. - memset(&Out::First, 0, sizeof(Out)); + memset(&Out::first, 0, sizeof(Out)); - auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; + auto add = [](InputSectionBase *sec) { inputSections.push_back(sec); }; - In.ShStrTab = make(".shstrtab", false); + in.shStrTab = make(".shstrtab", false); - Out::ProgramHeaders = make("", 0, SHF_ALLOC); - Out::ProgramHeaders->Alignment = Config->Wordsize; + Out::programHeaders = make("", 0, SHF_ALLOC); + Out::programHeaders->alignment = config->wordsize; - if (Config->Strip != StripPolicy::All) { - In.StrTab = make(".strtab", false); - In.SymTab = make>(*In.StrTab); - In.SymTabShndx = make(); + if (config->strip != StripPolicy::All) { + in.strTab = make(".strtab", false); + in.symTab = make>(*in.strTab); + in.symTabShndx = make(); } - In.Bss = make(".bss", 0, 1); - Add(In.Bss); + in.bss = make(".bss", 0, 1); + add(in.bss); // If there is a SECTIONS command and a .data.rel.ro section name use name // .data.rel.ro.bss so that we match in the .data.rel.ro output section. // This makes sure our relro is contiguous. - bool HasDataRelRo = - Script->HasSectionsCommand && findSection(".data.rel.ro", 0); - In.BssRelRo = - make(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); - Add(In.BssRelRo); + bool hasDataRelRo = + script->hasSectionsCommand && findSection(".data.rel.ro", 0); + in.bssRelRo = + make(hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); + add(in.bssRelRo); // Add MIPS-specific sections. - if (Config->EMachine == EM_MIPS) { - if (!Config->Shared && Config->HasDynSymTab) { - In.MipsRldMap = make(); - Add(In.MipsRldMap); - } - if (auto *Sec = MipsAbiFlagsSection::create()) - Add(Sec); - if (auto *Sec = MipsOptionsSection::create()) - Add(Sec); - if (auto *Sec = MipsReginfoSection::create()) - Add(Sec); - } - - for (Partition &Part : Partitions) { - auto Add = [&](InputSectionBase *Sec) { - Sec->Partition = Part.getNumber(); - InputSections.push_back(Sec); + if (config->emachine == EM_MIPS) { + if (!config->shared && config->hasDynSymTab) { + in.mipsRldMap = make(); + add(in.mipsRldMap); + } + if (auto *sec = MipsAbiFlagsSection::create()) + add(sec); + if (auto *sec = MipsOptionsSection::create()) + add(sec); + if (auto *sec = MipsReginfoSection::create()) + add(sec); + } + + for (Partition &part : partitions) { + auto add = [&](InputSectionBase *sec) { + sec->partition = part.getNumber(); + inputSections.push_back(sec); }; - if (!Part.Name.empty()) { - Part.ElfHeader = make>(); - Part.ElfHeader->Name = Part.Name; - Add(Part.ElfHeader); - - Part.ProgramHeaders = make>(); - Add(Part.ProgramHeaders); - } - - if (Config->BuildId != BuildIdKind::None) { - Part.BuildId = make(); - Add(Part.BuildId); - } - - Part.DynStrTab = make(".dynstr", true); - Part.DynSymTab = make>(*Part.DynStrTab); - Part.Dynamic = make>(); - if (Config->AndroidPackDynRelocs) { - Part.RelaDyn = make>( - Config->IsRela ? ".rela.dyn" : ".rel.dyn"); + if (!part.name.empty()) { + part.elfHeader = make>(); + part.elfHeader->name = part.name; + add(part.elfHeader); + + part.programHeaders = make>(); + add(part.programHeaders); + } + + if (config->buildId != BuildIdKind::None) { + part.buildId = make(); + add(part.buildId); + } + + part.dynStrTab = make(".dynstr", true); + part.dynSymTab = make>(*part.dynStrTab); + part.dynamic = make>(); + if (config->androidPackDynRelocs) { + part.relaDyn = make>( + config->isRela ? ".rela.dyn" : ".rel.dyn"); } else { - Part.RelaDyn = make>( - Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); + part.relaDyn = make>( + config->isRela ? ".rela.dyn" : ".rel.dyn", config->zCombreloc); } if (needsInterpSection()) - Add(createInterpSection()); + add(createInterpSection()); - if (Config->HasDynSymTab) { - Part.DynSymTab = make>(*Part.DynStrTab); - Add(Part.DynSymTab); - - Part.VerSym = make(); - Add(Part.VerSym); - - if (!Config->VersionDefinitions.empty()) { - Part.VerDef = make(); - Add(Part.VerDef); + if (config->hasDynSymTab) { + part.dynSymTab = make>(*part.dynStrTab); + add(part.dynSymTab); + + part.verSym = make(); + add(part.verSym); + + if (!config->versionDefinitions.empty()) { + part.verDef = make(); + add(part.verDef); } - Part.VerNeed = make>(); - Add(Part.VerNeed); + part.verNeed = make>(); + add(part.verNeed); - if (Config->GnuHash) { - Part.GnuHashTab = make(); - Add(Part.GnuHashTab); + if (config->gnuHash) { + part.gnuHashTab = make(); + add(part.gnuHashTab); } - if (Config->SysvHash) { - Part.HashTab = make(); - Add(Part.HashTab); + if (config->sysvHash) { + part.hashTab = make(); + add(part.hashTab); } - Add(Part.Dynamic); - Add(Part.DynStrTab); - Add(Part.RelaDyn); + add(part.dynamic); + add(part.dynStrTab); + add(part.relaDyn); } - if (Config->RelrPackDynRelocs) { - Part.RelrDyn = make>(); - Add(Part.RelrDyn); + if (config->relrPackDynRelocs) { + part.relrDyn = make>(); + add(part.relrDyn); } - if (!Config->Relocatable) { - if (Config->EhFrameHdr) { - Part.EhFrameHdr = make(); - Add(Part.EhFrameHdr); + if (!config->relocatable) { + if (config->ehFrameHdr) { + part.ehFrameHdr = make(); + add(part.ehFrameHdr); } - Part.EhFrame = make(); - Add(Part.EhFrame); + part.ehFrame = make(); + add(part.ehFrame); } - if (Config->EMachine == EM_ARM && !Config->Relocatable) { + if (config->emachine == EM_ARM && !config->relocatable) { // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx // InputSections. - Part.ARMExidx = make(); - Add(Part.ARMExidx); + part.armExidx = make(); + add(part.armExidx); } } - if (Partitions.size() != 1) { + if (partitions.size() != 1) { // Create the partition end marker. This needs to be in partition number 255 // so that it is sorted after all other partitions. It also has other // special handling (see createPhdrs() and combineEhSections()). - In.PartEnd = make(".part.end", Config->MaxPageSize, 1); - In.PartEnd->Partition = 255; - Add(In.PartEnd); - - In.PartIndex = make(); - addOptionalRegular("__part_index_begin", In.PartIndex, 0); - addOptionalRegular("__part_index_end", In.PartIndex, - In.PartIndex->getSize()); - Add(In.PartIndex); + in.partEnd = make(".part.end", config->maxPageSize, 1); + in.partEnd->partition = 255; + add(in.partEnd); + + in.partIndex = make(); + addOptionalRegular("__part_index_begin", in.partIndex, 0); + addOptionalRegular("__part_index_end", in.partIndex, + in.partIndex->getSize()); + add(in.partIndex); } // Add .got. MIPS' .got is so different from the other archs, // it has its own class. - if (Config->EMachine == EM_MIPS) { - In.MipsGot = make(); - Add(In.MipsGot); + if (config->emachine == EM_MIPS) { + in.mipsGot = make(); + add(in.mipsGot); } else { - In.Got = make(); - Add(In.Got); + in.got = make(); + add(in.got); } - if (Config->EMachine == EM_PPC) { - In.PPC32Got2 = make(); - Add(In.PPC32Got2); + if (config->emachine == EM_PPC) { + in.ppc32Got2 = make(); + add(in.ppc32Got2); } - if (Config->EMachine == EM_PPC64) { - In.PPC64LongBranchTarget = make(); - Add(In.PPC64LongBranchTarget); + if (config->emachine == EM_PPC64) { + in.ppc64LongBranchTarget = make(); + add(in.ppc64LongBranchTarget); } - if (Config->EMachine == EM_RISCV) { - In.RISCVSdata = make(); - Add(In.RISCVSdata); + if (config->emachine == EM_RISCV) { + in.riscvSdata = make(); + add(in.riscvSdata); } - In.GotPlt = make(); - Add(In.GotPlt); - In.IgotPlt = make(); - Add(In.IgotPlt); + in.gotPlt = make(); + add(in.gotPlt); + in.igotPlt = make(); + add(in.igotPlt); // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat // it as a relocation and ensure the referenced section is created. - if (ElfSym::GlobalOffsetTable && Config->EMachine != EM_MIPS) { - if (Target->GotBaseSymInGotPlt) - In.GotPlt->HasGotPltOffRel = true; + if (ElfSym::globalOffsetTable && config->emachine != EM_MIPS) { + if (target->gotBaseSymInGotPlt) + in.gotPlt->hasGotPltOffRel = true; else - In.Got->HasGotOffRel = true; + in.got->hasGotOffRel = true; } - if (Config->GdbIndex) - Add(GdbIndexSection::create()); + if (config->gdbIndex) + add(GdbIndexSection::create()); // We always need to add rel[a].plt to output if it has entries. // Even for static linking it can contain R_[*]_IRELATIVE relocations. - In.RelaPlt = make>( - Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); - Add(In.RelaPlt); + in.relaPlt = make>( + config->isRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); + add(in.relaPlt); // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure // that the IRelative relocations are processed last by the dynamic loader. @@ -510,36 +510,36 @@ // packing is enabled because that would cause a section type mismatch. // However, because the Android dynamic loader reads .rel.plt after .rel.dyn, // we can get the desired behaviour by placing the iplt section in .rel.plt. - In.RelaIplt = make>( - (Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs) + in.relaIplt = make>( + (config->emachine == EM_ARM && !config->androidPackDynRelocs) ? ".rel.dyn" - : In.RelaPlt->Name, + : in.relaPlt->name, false /*Sort*/); - Add(In.RelaIplt); + add(in.relaIplt); - In.Plt = make(false); - Add(In.Plt); - In.Iplt = make(true); - Add(In.Iplt); + in.plt = make(false); + add(in.plt); + in.iplt = make(true); + add(in.iplt); - if (Config->AndFeatures) - Add(make()); + if (config->andFeatures) + add(make()); // .note.GNU-stack is always added when we are creating a re-linkable // object file. Other linkers are using the presence of this marker // section to control the executable-ness of the stack area, but that // is irrelevant these days. Stack area should always be non-executable // by default. So we emit this section unconditionally. - if (Config->Relocatable) - Add(make()); + if (config->relocatable) + add(make()); - if (In.SymTab) - Add(In.SymTab); - if (In.SymTabShndx) - Add(In.SymTabShndx); - Add(In.ShStrTab); - if (In.StrTab) - Add(In.StrTab); + if (in.symTab) + add(in.symTab); + if (in.symTabShndx) + add(in.symTabShndx); + add(in.shStrTab); + if (in.strTab) + add(in.strTab); } // The main function of the writer. @@ -555,22 +555,22 @@ // Some input sections that are used for exception handling need to be moved // into synthetic sections. Do that now so that they aren't assigned to // output sections in the usual way. - if (!Config->Relocatable) + if (!config->relocatable) combineEhSections(); // We want to process linker script commands. When SECTIONS command // is given we let it create sections. - Script->processSectionCommands(); + script->processSectionCommands(); // Linker scripts controls how input sections are assigned to output sections. // Input sections that were not handled by scripts are called "orphans", and // they are assigned to output sections by the default rule. Process that. - Script->addOrphanSections(); + script->addOrphanSections(); - if (Config->Discard != DiscardPolicy::All) + if (config->discard != DiscardPolicy::All) copyLocalSymbols(); - if (Config->CopyRelocs) + if (config->copyRelocs) addSectionSymbols(); // Now that we have a complete set of output sections. This function @@ -582,35 +582,35 @@ if (errorCount()) return; - Script->assignAddresses(); + script->assignAddresses(); // If -compressed-debug-sections is specified, we need to compress // .debug_* sections. Do it right now because it changes the size of // output sections. - for (OutputSection *Sec : OutputSections) - Sec->maybeCompress(); + for (OutputSection *sec : outputSections) + sec->maybeCompress(); - Script->allocateHeaders(Main->Phdrs); + script->allocateHeaders(mainPart->phdrs); // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a // 0 sized region. This has to be done late since only after assignAddresses // we know the size of the sections. - for (Partition &Part : Partitions) - removeEmptyPTLoad(Part.Phdrs); + for (Partition &part : partitions) + removeEmptyPTLoad(part.phdrs); - if (!Config->OFormatBinary) + if (!config->oFormatBinary) assignFileOffsets(); else assignFileOffsetsBinary(); - for (Partition &Part : Partitions) - setPhdrs(Part); + for (Partition &part : partitions) + setPhdrs(part); - if (Config->Relocatable) - for (OutputSection *Sec : OutputSections) - Sec->Addr = 0; + if (config->relocatable) + for (OutputSection *sec : outputSections) + sec->addr = 0; - if (Config->CheckSections) + if (config->checkSections) checkSections(); // It does not make sense try to open the file if we have error already. @@ -621,7 +621,7 @@ if (errorCount()) return; - if (!Config->OFormatBinary) { + if (!config->oFormatBinary) { writeTrapInstr(); writeHeader(); writeSections(); @@ -641,20 +641,20 @@ if (errorCount()) return; - if (auto E = Buffer->commit()) - error("failed to write to the output file: " + toString(std::move(E))); + if (auto e = buffer->commit()) + error("failed to write to the output file: " + toString(std::move(e))); } -static bool shouldKeepInSymtab(const Defined &Sym) { - if (Sym.isSection()) +static bool shouldKeepInSymtab(const Defined &sym) { + if (sym.isSection()) return false; - if (Config->Discard == DiscardPolicy::None) + if (config->discard == DiscardPolicy::None) return true; // If -emit-reloc is given, all symbols including local ones need to be // copied because they may be referenced by relocations. - if (Config->EmitRelocs) + if (config->emitRelocs) return true; // In ELF assembly .L symbols are normally discarded by the assembler. @@ -662,62 +662,62 @@ // * --discard-locals is used. // * The symbol is in a SHF_MERGE section, which is normally the reason for // the assembler keeping the .L symbol. - StringRef Name = Sym.getName(); - bool IsLocal = Name.startswith(".L") || Name.empty(); - if (!IsLocal) + StringRef name = sym.getName(); + bool isLocal = name.startswith(".L") || name.empty(); + if (!isLocal) return true; - if (Config->Discard == DiscardPolicy::Locals) + if (config->discard == DiscardPolicy::Locals) return false; - SectionBase *Sec = Sym.Section; - return !Sec || !(Sec->Flags & SHF_MERGE); + SectionBase *sec = sym.section; + return !sec || !(sec->flags & SHF_MERGE); } -static bool includeInSymtab(const Symbol &B) { - if (!B.isLocal() && !B.IsUsedInRegularObj) +static bool includeInSymtab(const Symbol &b) { + if (!b.isLocal() && !b.isUsedInRegularObj) return false; - if (auto *D = dyn_cast(&B)) { + if (auto *d = dyn_cast(&b)) { // Always include absolute symbols. - SectionBase *Sec = D->Section; - if (!Sec) + SectionBase *sec = d->section; + if (!sec) return true; - Sec = Sec->Repl; + sec = sec->repl; // Exclude symbols pointing to garbage-collected sections. - if (isa(Sec) && !Sec->isLive()) + if (isa(sec) && !sec->isLive()) return false; - if (auto *S = dyn_cast(Sec)) - if (!S->getSectionPiece(D->Value)->Live) + if (auto *s = dyn_cast(sec)) + if (!s->getSectionPiece(d->value)->live) return false; return true; } - return B.Used; + return b.used; } // Local symbols are not in the linker's symbol table. This function scans // each object file's symbol table to copy local symbols to the output. template void Writer::copyLocalSymbols() { - if (!In.SymTab) + if (!in.symTab) return; - for (InputFile *File : ObjectFiles) { - ObjFile *F = cast>(File); - for (Symbol *B : F->getLocalSymbols()) { - if (!B->isLocal()) - fatal(toString(F) + + for (InputFile *file : objectFiles) { + ObjFile *f = cast>(file); + for (Symbol *b : f->getLocalSymbols()) { + if (!b->isLocal()) + fatal(toString(f) + ": broken object: getLocalSymbols returns a non-local symbol"); - auto *DR = dyn_cast(B); + auto *dr = dyn_cast(b); // No reason to keep local undefined symbol in symtab. - if (!DR) + if (!dr) continue; - if (!includeInSymtab(*B)) + if (!includeInSymtab(*b)) continue; - if (!shouldKeepInSymtab(*DR)) + if (!shouldKeepInSymtab(*dr)) continue; - In.SymTab->addSymbol(B); + in.symTab->addSymbol(b); } } } @@ -727,33 +727,33 @@ // referring to a section (that happens if the section is a synthetic one), we // don't create a section symbol for that section. template void Writer::addSectionSymbols() { - for (BaseCommand *Base : Script->SectionCommands) { - auto *Sec = dyn_cast(Base); - if (!Sec) + for (BaseCommand *base : script->sectionCommands) { + auto *sec = dyn_cast(base); + if (!sec) continue; - auto I = llvm::find_if(Sec->SectionCommands, [](BaseCommand *Base) { - if (auto *ISD = dyn_cast(Base)) - return !ISD->Sections.empty(); + auto i = llvm::find_if(sec->sectionCommands, [](BaseCommand *base) { + if (auto *isd = dyn_cast(base)) + return !isd->sections.empty(); return false; }); - if (I == Sec->SectionCommands.end()) + if (i == sec->sectionCommands.end()) continue; - InputSection *IS = cast(*I)->Sections[0]; + InputSection *isec = cast(*i)->sections[0]; // Relocations are not using REL[A] section symbols. - if (IS->Type == SHT_REL || IS->Type == SHT_RELA) + if (isec->type == SHT_REL || isec->type == SHT_RELA) continue; // Unlike other synthetic sections, mergeable output sections contain data // copied from input sections, and there may be a relocation pointing to its // contents if -r or -emit-reloc are given. - if (isa(IS) && !(IS->Flags & SHF_MERGE)) + if (isa(isec) && !(isec->flags & SHF_MERGE)) continue; - auto *Sym = - make(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION, - /*Value=*/0, /*Size=*/0, IS); - In.SymTab->addSymbol(Sym); + auto *sym = + make(isec->file, "", STB_LOCAL, /*StOther=*/0, STT_SECTION, + /*Value=*/0, /*Size=*/0, isec); + in.symTab->addSymbol(sym); } } @@ -763,25 +763,25 @@ // // This function returns true if a section needs to be put into a // PT_GNU_RELRO segment. -static bool isRelroSection(const OutputSection *Sec) { - if (!Config->ZRelro) +static bool isRelroSection(const OutputSection *sec) { + if (!config->zRelro) return false; - uint64_t Flags = Sec->Flags; + uint64_t flags = sec->flags; // Non-allocatable or non-writable sections don't need RELRO because // they are not writable or not even mapped to memory in the first place. // RELRO is for sections that are essentially read-only but need to // be writable only at process startup to allow dynamic linker to // apply relocations. - if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE)) + if (!(flags & SHF_ALLOC) || !(flags & SHF_WRITE)) return false; // Once initialized, TLS data segments are used as data templates // for a thread-local storage. For each new thread, runtime // allocates memory for a TLS and copy templates there. No thread // are supposed to use templates directly. Thus, it can be in RELRO. - if (Flags & SHF_TLS) + if (flags & SHF_TLS) return true; // .init_array, .preinit_array and .fini_array contain pointers to @@ -790,15 +790,15 @@ // to change at runtime. But if you are an attacker, you could do // interesting things by manipulating pointers in .fini_array, for // example. So they are put into RELRO. - uint32_t Type = Sec->Type; - if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY || - Type == SHT_PREINIT_ARRAY) + uint32_t type = sec->type; + if (type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY || + type == SHT_PREINIT_ARRAY) return true; // .got contains pointers to external symbols. They are resolved by // the dynamic linker when a module is loaded into memory, and after // that they are not expected to change. So, it can be in RELRO. - if (In.Got && Sec == In.Got->getParent()) + if (in.got && sec == in.got->getParent()) return true; // .toc is a GOT-ish section for PowerPC64. Their contents are accessed @@ -806,30 +806,30 @@ // for accessing .got as well, .got and .toc need to be close enough in the // virtual address space. Usually, .toc comes just after .got. Since we place // .got into RELRO, .toc needs to be placed into RELRO too. - if (Sec->Name.equals(".toc")) + if (sec->name.equals(".toc")) return true; // .got.plt contains pointers to external function symbols. They are // by default resolved lazily, so we usually cannot put it into RELRO. // However, if "-z now" is given, the lazy symbol resolution is // disabled, which enables us to put it into RELRO. - if (Sec == In.GotPlt->getParent()) - return Config->ZNow; + if (sec == in.gotPlt->getParent()) + return config->zNow; // .dynamic section contains data for the dynamic linker, and // there's no need to write to it at runtime, so it's better to put // it into RELRO. - if (Sec->Name == ".dynamic") + if (sec->name == ".dynamic") return true; // Sections with some special names are put into RELRO. This is a // bit unfortunate because section names shouldn't be significant in // ELF in spirit. But in reality many linker features depend on // magic section names. - StringRef S = Sec->Name; - return S == ".data.rel.ro" || S == ".bss.rel.ro" || S == ".ctors" || - S == ".dtors" || S == ".jcr" || S == ".eh_frame" || - S == ".openbsd.randomdata"; + StringRef s = sec->name; + return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" || + s == ".dtors" || s == ".jcr" || s == ".eh_frame" || + s == ".openbsd.randomdata"; } // We compute a rank for each section. The rank indicates where the @@ -863,41 +863,41 @@ RF_MIPS_NOT_GOT = 1 << 0 }; -static unsigned getSectionRank(const OutputSection *Sec) { - unsigned Rank = Sec->Partition * RF_PARTITION; +static unsigned getSectionRank(const OutputSection *sec) { + unsigned rank = sec->partition * RF_PARTITION; // We want to put section specified by -T option first, so we // can start assigning VA starting from them later. - if (Config->SectionStartMap.count(Sec->Name)) - return Rank; - Rank |= RF_NOT_ADDR_SET; + if (config->sectionStartMap.count(sec->name)) + return rank; + rank |= RF_NOT_ADDR_SET; // Allocatable sections go first to reduce the total PT_LOAD size and // so debug info doesn't change addresses in actual code. - if (!(Sec->Flags & SHF_ALLOC)) - return Rank | RF_NOT_ALLOC; + if (!(sec->flags & SHF_ALLOC)) + return rank | RF_NOT_ALLOC; - if (Sec->Type == SHT_LLVM_PART_EHDR) - return Rank; - Rank |= RF_NOT_PART_EHDR; - - if (Sec->Type == SHT_LLVM_PART_PHDR) - return Rank; - Rank |= RF_NOT_PART_PHDR; + if (sec->type == SHT_LLVM_PART_EHDR) + return rank; + rank |= RF_NOT_PART_EHDR; + + if (sec->type == SHT_LLVM_PART_PHDR) + return rank; + rank |= RF_NOT_PART_PHDR; // Put .interp first because some loaders want to see that section // on the first page of the executable file when loaded into memory. - if (Sec->Name == ".interp") - return Rank; - Rank |= RF_NOT_INTERP; + if (sec->name == ".interp") + return rank; + rank |= RF_NOT_INTERP; // Put .note sections (which make up one PT_NOTE) at the beginning so that // they are likely to be included in a core file even if core file size is // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be // included in a core to match core files with executables. - if (Sec->Type == SHT_NOTE) - return Rank; - Rank |= RF_NOT_NOTE; + if (sec->type == SHT_NOTE) + return rank; + rank |= RF_NOT_NOTE; // Sort sections based on their access permission in the following // order: R, RX, RWX, RW. This order is based on the following @@ -910,22 +910,22 @@ // between .text and .data. // * Writable sections come last, such that .bss lands at the very // end of the last PT_LOAD. - bool IsExec = Sec->Flags & SHF_EXECINSTR; - bool IsWrite = Sec->Flags & SHF_WRITE; + bool isExec = sec->flags & SHF_EXECINSTR; + bool isWrite = sec->flags & SHF_WRITE; - if (IsExec) { - if (IsWrite) - Rank |= RF_EXEC_WRITE; + if (isExec) { + if (isWrite) + rank |= RF_EXEC_WRITE; else - Rank |= RF_EXEC; - } else if (IsWrite) { - Rank |= RF_WRITE; - } else if (Sec->Type == SHT_PROGBITS) { + rank |= RF_EXEC; + } else if (isWrite) { + rank |= RF_WRITE; + } else if (sec->type == SHT_PROGBITS) { // Make non-executable and non-writable PROGBITS sections (e.g .rodata // .eh_frame) closer to .text. They likely contain PC or GOT relative // relocations and there could be relocation overflow if other huge sections // (.dynstr .dynsym) were placed in between. - Rank |= RF_RODATA; + rank |= RF_RODATA; } // Place RelRo sections first. After considering SHT_NOBITS below, the @@ -933,8 +933,8 @@ // where | marks where page alignment happens. An alternative ordering is // PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro .bss.rel.ro) | .bss), but it may // waste more bytes due to 2 alignment places. - if (!isRelroSection(Sec)) - Rank |= RF_NOT_RELRO; + if (!isRelroSection(sec)) + rank |= RF_NOT_RELRO; // If we got here we know that both A and B are in the same PT_LOAD. @@ -942,73 +942,73 @@ // PT_LOAD, so stick TLS sections directly before the other RelRo R/W // sections. Since p_filesz can be less than p_memsz, place NOBITS sections // after PROGBITS. - if (!(Sec->Flags & SHF_TLS)) - Rank |= RF_NOT_TLS; + if (!(sec->flags & SHF_TLS)) + rank |= RF_NOT_TLS; // Within TLS sections, or within other RelRo sections, or within non-RelRo // sections, place non-NOBITS sections first. - if (Sec->Type == SHT_NOBITS) - Rank |= RF_BSS; + if (sec->type == SHT_NOBITS) + rank |= RF_BSS; // Some architectures have additional ordering restrictions for sections // within the same PT_LOAD. - if (Config->EMachine == EM_PPC64) { + if (config->emachine == EM_PPC64) { // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections // that we would like to make sure appear is a specific order to maximize // their coverage by a single signed 16-bit offset from the TOC base // pointer. Conversely, the special .tocbss section should be first among // all SHT_NOBITS sections. This will put it next to the loaded special // PPC64 sections (and, thus, within reach of the TOC base pointer). - StringRef Name = Sec->Name; - if (Name != ".tocbss") - Rank |= RF_PPC_NOT_TOCBSS; + StringRef name = sec->name; + if (name != ".tocbss") + rank |= RF_PPC_NOT_TOCBSS; - if (Name == ".toc1") - Rank |= RF_PPC_TOCL; + if (name == ".toc1") + rank |= RF_PPC_TOCL; - if (Name == ".toc") - Rank |= RF_PPC_TOC; + if (name == ".toc") + rank |= RF_PPC_TOC; - if (Name == ".got") - Rank |= RF_PPC_GOT; + if (name == ".got") + rank |= RF_PPC_GOT; - if (Name == ".branch_lt") - Rank |= RF_PPC_BRANCH_LT; + if (name == ".branch_lt") + rank |= RF_PPC_BRANCH_LT; } - if (Config->EMachine == EM_MIPS) { + if (config->emachine == EM_MIPS) { // All sections with SHF_MIPS_GPREL flag should be grouped together // because data in these sections is addressable with a gp relative address. - if (Sec->Flags & SHF_MIPS_GPREL) - Rank |= RF_MIPS_GPREL; + if (sec->flags & SHF_MIPS_GPREL) + rank |= RF_MIPS_GPREL; - if (Sec->Name != ".got") - Rank |= RF_MIPS_NOT_GOT; + if (sec->name != ".got") + rank |= RF_MIPS_NOT_GOT; } - return Rank; + return rank; } -static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { - const OutputSection *A = cast(ACmd); - const OutputSection *B = cast(BCmd); +static bool compareSections(const BaseCommand *aCmd, const BaseCommand *bCmd) { + const OutputSection *a = cast(aCmd); + const OutputSection *b = cast(bCmd); - if (A->SortRank != B->SortRank) - return A->SortRank < B->SortRank; + if (a->sortRank != b->sortRank) + return a->sortRank < b->sortRank; - if (!(A->SortRank & RF_NOT_ADDR_SET)) - return Config->SectionStartMap.lookup(A->Name) < - Config->SectionStartMap.lookup(B->Name); + if (!(a->sortRank & RF_NOT_ADDR_SET)) + return config->sectionStartMap.lookup(a->name) < + config->sectionStartMap.lookup(b->name); return false; } -void PhdrEntry::add(OutputSection *Sec) { - LastSec = Sec; - if (!FirstSec) - FirstSec = Sec; - p_align = std::max(p_align, Sec->Alignment); +void PhdrEntry::add(OutputSection *sec) { + lastSec = sec; + if (!firstSec) + firstSec = sec; + p_align = std::max(p_align, sec->alignment); if (p_type == PT_LOAD) - Sec->PtLoad = this; + sec->ptLoad = this; } // The beginning and the ending of .rel[a].plt section are marked @@ -1018,39 +1018,39 @@ // need these symbols, since IRELATIVE relocs are resolved through GOT // and PLT. For details, see http://www.airs.com/blog/archives/403. template void Writer::addRelIpltSymbols() { - if (Config->Relocatable || needsInterpSection()) + if (config->relocatable || needsInterpSection()) return; // By default, __rela_iplt_{start,end} belong to a dummy section 0 // because .rela.plt might be empty and thus removed from output. // We'll override Out::ElfHeader with In.RelaIplt later when we are // sure that .rela.plt exists in output. - ElfSym::RelaIpltStart = addOptionalRegular( - Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start", - Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); - - ElfSym::RelaIpltEnd = addOptionalRegular( - Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end", - Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); + ElfSym::relaIpltStart = addOptionalRegular( + config->isRela ? "__rela_iplt_start" : "__rel_iplt_start", + Out::elfHeader, 0, STV_HIDDEN, STB_WEAK); + + ElfSym::relaIpltEnd = addOptionalRegular( + config->isRela ? "__rela_iplt_end" : "__rel_iplt_end", + Out::elfHeader, 0, STV_HIDDEN, STB_WEAK); } template void Writer::forEachRelSec( - llvm::function_ref Fn) { + llvm::function_ref fn) { // Scan all relocations. Each relocation goes through a series // of tests to determine if it needs special treatment, such as // creating GOT, PLT, copy relocations, etc. // Note that relocations for non-alloc sections are directly // processed by InputSection::relocateNonAlloc. - for (InputSectionBase *IS : InputSections) - if (IS->isLive() && isa(IS) && (IS->Flags & SHF_ALLOC)) - Fn(*IS); - for (Partition &Part : Partitions) { - for (EhInputSection *ES : Part.EhFrame->Sections) - Fn(*ES); - if (Part.ARMExidx && Part.ARMExidx->isLive()) - for (InputSection *Ex : Part.ARMExidx->ExidxSections) - Fn(*Ex); + for (InputSectionBase *isec : inputSections) + if (isec->isLive() && isa(isec) && (isec->flags & SHF_ALLOC)) + fn(*isec); + for (Partition &part : partitions) { + for (EhInputSection *es : part.ehFrame->sections) + fn(*es); + if (part.armExidx && part.armExidx->isLive()) + for (InputSection *ex : part.armExidx->exidxSections) + fn(*ex); } } @@ -1060,78 +1060,78 @@ // time any references to these symbols are processed and is equivalent to // defining these symbols explicitly in the linker script. template void Writer::setReservedSymbolSections() { - if (ElfSym::GlobalOffsetTable) { + if (ElfSym::globalOffsetTable) { // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually // to the start of the .got or .got.plt section. - InputSection *GotSection = In.GotPlt; - if (!Target->GotBaseSymInGotPlt) - GotSection = In.MipsGot ? cast(In.MipsGot) - : cast(In.Got); - ElfSym::GlobalOffsetTable->Section = GotSection; + InputSection *gotSection = in.gotPlt; + if (!target->gotBaseSymInGotPlt) + gotSection = in.mipsGot ? cast(in.mipsGot) + : cast(in.got); + ElfSym::globalOffsetTable->section = gotSection; } // .rela_iplt_{start,end} mark the start and the end of .rela.plt section. - if (ElfSym::RelaIpltStart && In.RelaIplt->isNeeded()) { - ElfSym::RelaIpltStart->Section = In.RelaIplt; - ElfSym::RelaIpltEnd->Section = In.RelaIplt; - ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize(); + if (ElfSym::relaIpltStart && in.relaIplt->isNeeded()) { + ElfSym::relaIpltStart->section = in.relaIplt; + ElfSym::relaIpltEnd->section = in.relaIplt; + ElfSym::relaIpltEnd->value = in.relaIplt->getSize(); } - PhdrEntry *Last = nullptr; - PhdrEntry *LastRO = nullptr; - - for (Partition &Part : Partitions) { - for (PhdrEntry *P : Part.Phdrs) { - if (P->p_type != PT_LOAD) + PhdrEntry *last = nullptr; + PhdrEntry *lastRO = nullptr; + + for (Partition &part : partitions) { + for (PhdrEntry *p : part.phdrs) { + if (p->p_type != PT_LOAD) continue; - Last = P; - if (!(P->p_flags & PF_W)) - LastRO = P; + last = p; + if (!(p->p_flags & PF_W)) + lastRO = p; } } - if (LastRO) { + if (lastRO) { // _etext is the first location after the last read-only loadable segment. - if (ElfSym::Etext1) - ElfSym::Etext1->Section = LastRO->LastSec; - if (ElfSym::Etext2) - ElfSym::Etext2->Section = LastRO->LastSec; + if (ElfSym::etext1) + ElfSym::etext1->section = lastRO->lastSec; + if (ElfSym::etext2) + ElfSym::etext2->section = lastRO->lastSec; } - if (Last) { + if (last) { // _edata points to the end of the last mapped initialized section. - OutputSection *Edata = nullptr; - for (OutputSection *OS : OutputSections) { - if (OS->Type != SHT_NOBITS) - Edata = OS; - if (OS == Last->LastSec) + OutputSection *edata = nullptr; + for (OutputSection *os : outputSections) { + if (os->type != SHT_NOBITS) + edata = os; + if (os == last->lastSec) break; } - if (ElfSym::Edata1) - ElfSym::Edata1->Section = Edata; - if (ElfSym::Edata2) - ElfSym::Edata2->Section = Edata; + if (ElfSym::edata1) + ElfSym::edata1->section = edata; + if (ElfSym::edata2) + ElfSym::edata2->section = edata; // _end is the first location after the uninitialized data region. - if (ElfSym::End1) - ElfSym::End1->Section = Last->LastSec; - if (ElfSym::End2) - ElfSym::End2->Section = Last->LastSec; + if (ElfSym::end1) + ElfSym::end1->section = last->lastSec; + if (ElfSym::end2) + ElfSym::end2->section = last->lastSec; } - if (ElfSym::Bss) - ElfSym::Bss->Section = findSection(".bss"); + if (ElfSym::bss) + ElfSym::bss->section = findSection(".bss"); // Setup MIPS _gp_disp/__gnu_local_gp symbols which should // be equal to the _gp symbol's value. - if (ElfSym::MipsGp) { + if (ElfSym::mipsGp) { // Find GP-relative section with the lowest address // and use this address to calculate default _gp value. - for (OutputSection *OS : OutputSections) { - if (OS->Flags & SHF_MIPS_GPREL) { - ElfSym::MipsGp->Section = OS; - ElfSym::MipsGp->Value = 0x7ff0; + for (OutputSection *os : outputSections) { + if (os->flags & SHF_MIPS_GPREL) { + ElfSym::mipsGp->section = os; + ElfSym::mipsGp->value = 0x7ff0; break; } } @@ -1142,13 +1142,13 @@ // The more branches in getSectionRank that match, the more similar they are. // Since each branch corresponds to a bit flag, we can just use // countLeadingZeros. -static int getRankProximityAux(OutputSection *A, OutputSection *B) { - return countLeadingZeros(A->SortRank ^ B->SortRank); +static int getRankProximityAux(OutputSection *a, OutputSection *b) { + return countLeadingZeros(a->sortRank ^ b->sortRank); } -static int getRankProximity(OutputSection *A, BaseCommand *B) { - auto *Sec = dyn_cast(B); - return (Sec && Sec->HasInputSections) ? getRankProximityAux(A, Sec) : -1; +static int getRankProximity(OutputSection *a, BaseCommand *b) { + auto *sec = dyn_cast(b); + return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1; } // When placing orphan sections, we want to place them after symbol assignments @@ -1165,9 +1165,9 @@ // /* The RW PT_LOAD starts here*/ // rw_sec : { *(rw_sec) } // would mean that the RW PT_LOAD would become unaligned. -static bool shouldSkip(BaseCommand *Cmd) { - if (auto *Assign = dyn_cast(Cmd)) - return Assign->Name != "."; +static bool shouldSkip(BaseCommand *cmd) { + if (auto *assign = dyn_cast(cmd)) + return assign->name != "."; return false; } @@ -1175,132 +1175,132 @@ // characteristics with their neighbors as possible. For example, if // both are rw, or both are tls. static std::vector::iterator -findOrphanPos(std::vector::iterator B, - std::vector::iterator E) { - OutputSection *Sec = cast(*E); +findOrphanPos(std::vector::iterator b, + std::vector::iterator e) { + OutputSection *sec = cast(*e); // Find the first element that has as close a rank as possible. - auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) { - return getRankProximity(Sec, A) < getRankProximity(Sec, B); + auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) { + return getRankProximity(sec, a) < getRankProximity(sec, b); }); - if (I == E) - return E; + if (i == e) + return e; // Consider all existing sections with the same proximity. - int Proximity = getRankProximity(Sec, *I); - for (; I != E; ++I) { - auto *CurSec = dyn_cast(*I); - if (!CurSec || !CurSec->HasInputSections) + int proximity = getRankProximity(sec, *i); + for (; i != e; ++i) { + auto *curSec = dyn_cast(*i); + if (!curSec || !curSec->hasInputSections) continue; - if (getRankProximity(Sec, CurSec) != Proximity || - Sec->SortRank < CurSec->SortRank) + if (getRankProximity(sec, curSec) != proximity || + sec->sortRank < curSec->sortRank) break; } - auto IsOutputSecWithInputSections = [](BaseCommand *Cmd) { - auto *OS = dyn_cast(Cmd); - return OS && OS->HasInputSections; + auto isOutputSecWithInputSections = [](BaseCommand *cmd) { + auto *os = dyn_cast(cmd); + return os && os->hasInputSections; }; - auto J = std::find_if(llvm::make_reverse_iterator(I), - llvm::make_reverse_iterator(B), - IsOutputSecWithInputSections); - I = J.base(); + auto j = std::find_if(llvm::make_reverse_iterator(i), + llvm::make_reverse_iterator(b), + isOutputSecWithInputSections); + i = j.base(); // As a special case, if the orphan section is the last section, put // it at the very end, past any other commands. // This matches bfd's behavior and is convenient when the linker script fully // specifies the start of the file, but doesn't care about the end (the non // alloc sections for example). - auto NextSec = std::find_if(I, E, IsOutputSecWithInputSections); - if (NextSec == E) - return E; - - while (I != E && shouldSkip(*I)) - ++I; - return I; + auto nextSec = std::find_if(i, e, isOutputSecWithInputSections); + if (nextSec == e) + return e; + + while (i != e && shouldSkip(*i)) + ++i; + return i; } // Builds section order for handling --symbol-ordering-file. static DenseMap buildSectionOrder() { - DenseMap SectionOrder; + DenseMap sectionOrder; // Use the rarely used option -call-graph-ordering-file to sort sections. - if (!Config->CallGraphProfile.empty()) + if (!config->callGraphProfile.empty()) return computeCallGraphProfileOrder(); - if (Config->SymbolOrderingFile.empty()) - return SectionOrder; + if (config->symbolOrderingFile.empty()) + return sectionOrder; struct SymbolOrderEntry { - int Priority; - bool Present; + int priority; + bool present; }; // Build a map from symbols to their priorities. Symbols that didn't // appear in the symbol ordering file have the lowest priority 0. // All explicitly mentioned symbols have negative (higher) priorities. - DenseMap SymbolOrder; - int Priority = -Config->SymbolOrderingFile.size(); - for (StringRef S : Config->SymbolOrderingFile) - SymbolOrder.insert({S, {Priority++, false}}); + DenseMap symbolOrder; + int priority = -config->symbolOrderingFile.size(); + for (StringRef s : config->symbolOrderingFile) + symbolOrder.insert({s, {priority++, false}}); // Build a map from sections to their priorities. - auto AddSym = [&](Symbol &Sym) { - auto It = SymbolOrder.find(Sym.getName()); - if (It == SymbolOrder.end()) + auto addSym = [&](Symbol &sym) { + auto it = symbolOrder.find(sym.getName()); + if (it == symbolOrder.end()) return; - SymbolOrderEntry &Ent = It->second; - Ent.Present = true; + SymbolOrderEntry &ent = it->second; + ent.present = true; - maybeWarnUnorderableSymbol(&Sym); + maybeWarnUnorderableSymbol(&sym); - if (auto *D = dyn_cast(&Sym)) { - if (auto *Sec = dyn_cast_or_null(D->Section)) { - int &Priority = SectionOrder[cast(Sec->Repl)]; - Priority = std::min(Priority, Ent.Priority); + if (auto *d = dyn_cast(&sym)) { + if (auto *sec = dyn_cast_or_null(d->section)) { + int &priority = sectionOrder[cast(sec->repl)]; + priority = std::min(priority, ent.priority); } } }; // We want both global and local symbols. We get the global ones from the // symbol table and iterate the object files for the local ones. - Symtab->forEachSymbol([&](Symbol *Sym) { - if (!Sym->isLazy()) - AddSym(*Sym); + symtab->forEachSymbol([&](Symbol *sym) { + if (!sym->isLazy()) + addSym(*sym); }); - for (InputFile *File : ObjectFiles) - for (Symbol *Sym : File->getSymbols()) - if (Sym->isLocal()) - AddSym(*Sym); - - if (Config->WarnSymbolOrdering) - for (auto OrderEntry : SymbolOrder) - if (!OrderEntry.second.Present) - warn("symbol ordering file: no such symbol: " + OrderEntry.first); + for (InputFile *file : objectFiles) + for (Symbol *sym : file->getSymbols()) + if (sym->isLocal()) + addSym(*sym); + + if (config->warnSymbolOrdering) + for (auto orderEntry : symbolOrder) + if (!orderEntry.second.present) + warn("symbol ordering file: no such symbol: " + orderEntry.first); - return SectionOrder; + return sectionOrder; } // Sorts the sections in ISD according to the provided section order. static void -sortISDBySectionOrder(InputSectionDescription *ISD, - const DenseMap &Order) { - std::vector UnorderedSections; - std::vector> OrderedSections; - uint64_t UnorderedSize = 0; - - for (InputSection *IS : ISD->Sections) { - auto I = Order.find(IS); - if (I == Order.end()) { - UnorderedSections.push_back(IS); - UnorderedSize += IS->getSize(); +sortISDBySectionOrder(InputSectionDescription *isd, + const DenseMap &order) { + std::vector unorderedSections; + std::vector> orderedSections; + uint64_t unorderedSize = 0; + + for (InputSection *isec : isd->sections) { + auto i = order.find(isec); + if (i == order.end()) { + unorderedSections.push_back(isec); + unorderedSize += isec->getSize(); continue; } - OrderedSections.push_back({IS, I->second}); + orderedSections.push_back({isec, i->second}); } - llvm::sort(OrderedSections, [&](std::pair A, - std::pair B) { - return A.second < B.second; + llvm::sort(orderedSections, [&](std::pair a, + std::pair b) { + return a.second < b.second; }); // Find an insertion point for the ordered section list in the unordered @@ -1330,46 +1330,46 @@ // of the second block of cold code can call the hot code without a thunk. So // we effectively double the amount of code that could potentially call into // the hot code without a thunk. - size_t InsPt = 0; - if (Target->getThunkSectionSpacing() && !OrderedSections.empty()) { - uint64_t UnorderedPos = 0; - for (; InsPt != UnorderedSections.size(); ++InsPt) { - UnorderedPos += UnorderedSections[InsPt]->getSize(); - if (UnorderedPos > UnorderedSize / 2) + size_t insPt = 0; + if (target->getThunkSectionSpacing() && !orderedSections.empty()) { + uint64_t unorderedPos = 0; + for (; insPt != unorderedSections.size(); ++insPt) { + unorderedPos += unorderedSections[insPt]->getSize(); + if (unorderedPos > unorderedSize / 2) break; } } - ISD->Sections.clear(); - for (InputSection *IS : makeArrayRef(UnorderedSections).slice(0, InsPt)) - ISD->Sections.push_back(IS); - for (std::pair P : OrderedSections) - ISD->Sections.push_back(P.first); - for (InputSection *IS : makeArrayRef(UnorderedSections).slice(InsPt)) - ISD->Sections.push_back(IS); + isd->sections.clear(); + for (InputSection *isec : makeArrayRef(unorderedSections).slice(0, insPt)) + isd->sections.push_back(isec); + for (std::pair p : orderedSections) + isd->sections.push_back(p.first); + for (InputSection *isec : makeArrayRef(unorderedSections).slice(insPt)) + isd->sections.push_back(isec); } -static void sortSection(OutputSection *Sec, - const DenseMap &Order) { - StringRef Name = Sec->Name; +static void sortSection(OutputSection *sec, + const DenseMap &order) { + StringRef name = sec->name; // Sort input sections by section name suffixes for // __attribute__((init_priority(N))). - if (Name == ".init_array" || Name == ".fini_array") { - if (!Script->HasSectionsCommand) - Sec->sortInitFini(); + if (name == ".init_array" || name == ".fini_array") { + if (!script->hasSectionsCommand) + sec->sortInitFini(); return; } // Sort input sections by the special rule for .ctors and .dtors. - if (Name == ".ctors" || Name == ".dtors") { - if (!Script->HasSectionsCommand) - Sec->sortCtorsDtors(); + if (name == ".ctors" || name == ".dtors") { + if (!script->hasSectionsCommand) + sec->sortCtorsDtors(); return; } // Never sort these. - if (Name == ".init" || Name == ".fini") + if (name == ".init" || name == ".fini") return; // .toc is allocated just after .got and is accessed using GOT-relative @@ -1377,67 +1377,67 @@ // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations. // To reduce the risk of relocation overflow, .toc contents are sorted so that // sections having smaller relocation offsets are at beginning of .toc - if (Config->EMachine == EM_PPC64 && Name == ".toc") { - if (Script->HasSectionsCommand) + if (config->emachine == EM_PPC64 && name == ".toc") { + if (script->hasSectionsCommand) return; - assert(Sec->SectionCommands.size() == 1); - auto *ISD = cast(Sec->SectionCommands[0]); - llvm::stable_sort(ISD->Sections, - [](const InputSection *A, const InputSection *B) -> bool { - return A->File->PPC64SmallCodeModelTocRelocs && - !B->File->PPC64SmallCodeModelTocRelocs; + assert(sec->sectionCommands.size() == 1); + auto *isd = cast(sec->sectionCommands[0]); + llvm::stable_sort(isd->sections, + [](const InputSection *a, const InputSection *b) -> bool { + return a->file->ppc64SmallCodeModelTocRelocs && + !b->file->ppc64SmallCodeModelTocRelocs; }); return; } // Sort input sections by priority using the list provided // by --symbol-ordering-file. - if (!Order.empty()) - for (BaseCommand *B : Sec->SectionCommands) - if (auto *ISD = dyn_cast(B)) - sortISDBySectionOrder(ISD, Order); + if (!order.empty()) + for (BaseCommand *b : sec->sectionCommands) + if (auto *isd = dyn_cast(b)) + sortISDBySectionOrder(isd, order); } // If no layout was provided by linker script, we want to apply default // sorting for special input sections. This also handles --symbol-ordering-file. template void Writer::sortInputSections() { // Build the order once since it is expensive. - DenseMap Order = buildSectionOrder(); - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - sortSection(Sec, Order); + DenseMap order = buildSectionOrder(); + for (BaseCommand *base : script->sectionCommands) + if (auto *sec = dyn_cast(base)) + sortSection(sec, order); } template void Writer::sortSections() { - Script->adjustSectionsBeforeSorting(); + script->adjustSectionsBeforeSorting(); // Don't sort if using -r. It is not necessary and we want to preserve the // relative order for SHF_LINK_ORDER sections. - if (Config->Relocatable) + if (config->relocatable) return; sortInputSections(); - for (BaseCommand *Base : Script->SectionCommands) { - auto *OS = dyn_cast(Base); - if (!OS) + for (BaseCommand *base : script->sectionCommands) { + auto *os = dyn_cast(base); + if (!os) continue; - OS->SortRank = getSectionRank(OS); + os->sortRank = getSectionRank(os); // We want to assign rude approximation values to OutSecOff fields // to know the relative order of the input sections. We use it for // sorting SHF_LINK_ORDER sections. See resolveShfLinkOrder(). - uint64_t I = 0; - for (InputSection *Sec : getInputSections(OS)) - Sec->OutSecOff = I++; + uint64_t i = 0; + for (InputSection *sec : getInputSections(os)) + sec->outSecOff = i++; } - if (!Script->HasSectionsCommand) { + if (!script->hasSectionsCommand) { // We know that all the OutputSections are contiguous in this case. - auto IsSection = [](BaseCommand *Base) { return isa(Base); }; + auto isSection = [](BaseCommand *base) { return isa(base); }; std::stable_sort( - llvm::find_if(Script->SectionCommands, IsSection), - llvm::find_if(llvm::reverse(Script->SectionCommands), IsSection).base(), + llvm::find_if(script->sectionCommands, isSection), + llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(), compareSections); return; } @@ -1481,84 +1481,84 @@ // after another commands. For the details, look at shouldSkip // function. - auto I = Script->SectionCommands.begin(); - auto E = Script->SectionCommands.end(); - auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) { - if (auto *Sec = dyn_cast(Base)) - return Sec->SectionIndex == UINT32_MAX; + auto i = script->sectionCommands.begin(); + auto e = script->sectionCommands.end(); + auto nonScriptI = std::find_if(i, e, [](BaseCommand *base) { + if (auto *sec = dyn_cast(base)) + return sec->sectionIndex == UINT32_MAX; return false; }); // Sort the orphan sections. - std::stable_sort(NonScriptI, E, compareSections); + std::stable_sort(nonScriptI, e, compareSections); // As a horrible special case, skip the first . assignment if it is before any // section. We do this because it is common to set a load address by starting // the script with ". = 0xabcd" and the expectation is that every section is // after that. - auto FirstSectionOrDotAssignment = - std::find_if(I, E, [](BaseCommand *Cmd) { return !shouldSkip(Cmd); }); - if (FirstSectionOrDotAssignment != E && - isa(**FirstSectionOrDotAssignment)) - ++FirstSectionOrDotAssignment; - I = FirstSectionOrDotAssignment; - - while (NonScriptI != E) { - auto Pos = findOrphanPos(I, NonScriptI); - OutputSection *Orphan = cast(*NonScriptI); + auto firstSectionOrDotAssignment = + std::find_if(i, e, [](BaseCommand *cmd) { return !shouldSkip(cmd); }); + if (firstSectionOrDotAssignment != e && + isa(**firstSectionOrDotAssignment)) + ++firstSectionOrDotAssignment; + i = firstSectionOrDotAssignment; + + while (nonScriptI != e) { + auto pos = findOrphanPos(i, nonScriptI); + OutputSection *orphan = cast(*nonScriptI); // As an optimization, find all sections with the same sort rank // and insert them with one rotate. - unsigned Rank = Orphan->SortRank; - auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) { - return cast(Cmd)->SortRank != Rank; + unsigned rank = orphan->sortRank; + auto end = std::find_if(nonScriptI + 1, e, [=](BaseCommand *cmd) { + return cast(cmd)->sortRank != rank; }); - std::rotate(Pos, NonScriptI, End); - NonScriptI = End; + std::rotate(pos, nonScriptI, end); + nonScriptI = end; } - Script->adjustSectionsAfterSorting(); + script->adjustSectionsAfterSorting(); } -static bool compareByFilePosition(InputSection *A, InputSection *B) { - InputSection *LA = A->getLinkOrderDep(); - InputSection *LB = B->getLinkOrderDep(); - OutputSection *AOut = LA->getParent(); - OutputSection *BOut = LB->getParent(); +static bool compareByFilePosition(InputSection *a, InputSection *b) { + InputSection *la = a->getLinkOrderDep(); + InputSection *lb = b->getLinkOrderDep(); + OutputSection *aOut = la->getParent(); + OutputSection *bOut = lb->getParent(); - if (AOut != BOut) - return AOut->SectionIndex < BOut->SectionIndex; - return LA->OutSecOff < LB->OutSecOff; + if (aOut != bOut) + return aOut->sectionIndex < bOut->sectionIndex; + return la->outSecOff < lb->outSecOff; } template void Writer::resolveShfLinkOrder() { - for (OutputSection *Sec : OutputSections) { - if (!(Sec->Flags & SHF_LINK_ORDER)) + for (OutputSection *sec : outputSections) { + if (!(sec->flags & SHF_LINK_ORDER)) continue; // Link order may be distributed across several InputSectionDescriptions // but sort must consider them all at once. - std::vector ScriptSections; - std::vector Sections; - for (BaseCommand *Base : Sec->SectionCommands) { - if (auto *ISD = dyn_cast(Base)) { - for (InputSection *&IS : ISD->Sections) { - ScriptSections.push_back(&IS); - Sections.push_back(IS); + std::vector scriptSections; + std::vector sections; + for (BaseCommand *base : sec->sectionCommands) { + if (auto *isd = dyn_cast(base)) { + for (InputSection *&isec : isd->sections) { + scriptSections.push_back(&isec); + sections.push_back(isec); } } } // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated // this processing inside the ARMExidxsyntheticsection::finalizeContents(). - if (!Config->Relocatable && Config->EMachine == EM_ARM && - Sec->Type == SHT_ARM_EXIDX) + if (!config->relocatable && config->emachine == EM_ARM && + sec->type == SHT_ARM_EXIDX) continue; - llvm::stable_sort(Sections, compareByFilePosition); + llvm::stable_sort(sections, compareByFilePosition); - for (int I = 0, N = Sections.size(); I < N; ++I) - *ScriptSections[I] = Sections[I]; + for (int i = 0, n = sections.size(); i < n; ++i) + *scriptSections[i] = sections[i]; } } @@ -1567,41 +1567,41 @@ // addresses we must converge to a fixed point. We do that here. See the comment // in Writer::finalizeSections(). template void Writer::finalizeAddressDependentContent() { - ThunkCreator TC; - AArch64Err843419Patcher A64P; + ThunkCreator tc; + AArch64Err843419Patcher a64p; // For some targets, like x86, this loop iterates only once. for (;;) { - bool Changed = false; + bool changed = false; - Script->assignAddresses(); + script->assignAddresses(); - if (Target->NeedsThunks) - Changed |= TC.createThunks(OutputSections); + if (target->needsThunks) + changed |= tc.createThunks(outputSections); - if (Config->FixCortexA53Errata843419) { - if (Changed) - Script->assignAddresses(); - Changed |= A64P.createFixes(); + if (config->fixCortexA53Errata843419) { + if (changed) + script->assignAddresses(); + changed |= a64p.createFixes(); } - if (In.MipsGot) - In.MipsGot->updateAllocSize(); + if (in.mipsGot) + in.mipsGot->updateAllocSize(); - for (Partition &Part : Partitions) { - Changed |= Part.RelaDyn->updateAllocSize(); - if (Part.RelrDyn) - Changed |= Part.RelrDyn->updateAllocSize(); + for (Partition &part : partitions) { + changed |= part.relaDyn->updateAllocSize(); + if (part.relrDyn) + changed |= part.relrDyn->updateAllocSize(); } - if (!Changed) + if (!changed) return; } } -static void finalizeSynthetic(SyntheticSection *Sec) { - if (Sec && Sec->isNeeded() && Sec->getParent()) - Sec->finalizeContents(); +static void finalizeSynthetic(SyntheticSection *sec) { + if (sec && sec->isNeeded() && sec->getParent()) + sec->finalizeContents(); } // In order to allow users to manipulate linker-synthesized sections, @@ -1620,90 +1620,90 @@ // All input synthetic sections that can be empty are placed after // all regular ones. We iterate over them all and exit at first // non-synthetic. - for (InputSectionBase *S : llvm::reverse(InputSections)) { - SyntheticSection *SS = dyn_cast(S); - if (!SS) + for (InputSectionBase *s : llvm::reverse(inputSections)) { + SyntheticSection *ss = dyn_cast(s); + if (!ss) return; - OutputSection *OS = SS->getParent(); - if (!OS || SS->isNeeded()) + OutputSection *os = ss->getParent(); + if (!os || ss->isNeeded()) continue; // If we reach here, then SS is an unused synthetic section and we want to // remove it from corresponding input section description of output section. - for (BaseCommand *B : OS->SectionCommands) - if (auto *ISD = dyn_cast(B)) - llvm::erase_if(ISD->Sections, - [=](InputSection *IS) { return IS == SS; }); + for (BaseCommand *b : os->sectionCommands) + if (auto *isd = dyn_cast(b)) + llvm::erase_if(isd->sections, + [=](InputSection *isec) { return isec == ss; }); } } // Returns true if a symbol can be replaced at load-time by a symbol // with the same name defined in other ELF executable or DSO. -static bool computeIsPreemptible(const Symbol &B) { - assert(!B.isLocal()); +static bool computeIsPreemptible(const Symbol &b) { + assert(!b.isLocal()); // Only symbols that appear in dynsym can be preempted. - if (!B.includeInDynsym()) + if (!b.includeInDynsym()) return false; // Only default visibility symbols can be preempted. - if (B.Visibility != STV_DEFAULT) + if (b.visibility != STV_DEFAULT) return false; // At this point copy relocations have not been created yet, so any // symbol that is not defined locally is preemptible. - if (!B.isDefined()) + if (!b.isDefined()) return true; // If we have a dynamic list it specifies which local symbols are preemptible. - if (Config->HasDynamicList) + if (config->hasDynamicList) return false; - if (!Config->Shared) + if (!config->shared) return false; // -Bsymbolic means that definitions are not preempted. - if (Config->Bsymbolic || (Config->BsymbolicFunctions && B.isFunc())) + if (config->bsymbolic || (config->bsymbolicFunctions && b.isFunc())) return false; return true; } // Create output section objects and add them to OutputSections. template void Writer::finalizeSections() { - Out::PreinitArray = findSection(".preinit_array"); - Out::InitArray = findSection(".init_array"); - Out::FiniArray = findSection(".fini_array"); + Out::preinitArray = findSection(".preinit_array"); + Out::initArray = findSection(".init_array"); + Out::finiArray = findSection(".fini_array"); // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. - if (!Config->Relocatable) { + if (!config->relocatable) { addStartEndSymbols(); - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - addStartStopSymbols(Sec); + for (BaseCommand *base : script->sectionCommands) + if (auto *sec = dyn_cast(base)) + addStartStopSymbols(sec); } // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type. // It should be okay as no one seems to care about the type. // Even the author of gold doesn't remember why gold behaves that way. // https://sourceware.org/ml/binutils/2002-03/msg00360.html - if (Main->Dynamic->Parent) - Symtab->addSymbol(Defined{/*File=*/nullptr, "_DYNAMIC", STB_WEAK, + if (mainPart->dynamic->parent) + symtab->addSymbol(Defined{/*File=*/nullptr, "_DYNAMIC", STB_WEAK, STV_HIDDEN, STT_NOTYPE, - /*Value=*/0, /*Size=*/0, Main->Dynamic}); + /*Value=*/0, /*Size=*/0, mainPart->dynamic}); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. // This symbol should only be defined in an executable. - if (Config->EMachine == EM_RISCV && !Config->Shared) - ElfSym::RISCVGlobalPointer = + if (config->emachine == EM_RISCV && !config->shared) + ElfSym::riscvGlobalPointer = addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800, STV_DEFAULT, STB_GLOBAL); - if (Config->EMachine == EM_X86_64) { + if (config->emachine == EM_X86_64) { // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a // way that: // @@ -1715,41 +1715,41 @@ // 2) is special cased in @tpoff computation. To satisfy 1), we define it as // an absolute symbol of zero. This is different from GNU linkers which // define _TLS_MODULE_BASE_ relative to the first TLS section. - Symbol *S = Symtab->find("_TLS_MODULE_BASE_"); - if (S && S->isUndefined()) { - S->resolve(Defined{/*File=*/nullptr, S->getName(), STB_GLOBAL, STV_HIDDEN, + Symbol *s = symtab->find("_TLS_MODULE_BASE_"); + if (s && s->isUndefined()) { + s->resolve(Defined{/*File=*/nullptr, s->getName(), STB_GLOBAL, STV_HIDDEN, STT_TLS, /*Value=*/0, 0, /*Section=*/nullptr}); - ElfSym::TlsModuleBase = cast(S); + ElfSym::tlsModuleBase = cast(s); } } // This responsible for splitting up .eh_frame section into // pieces. The relocation scan uses those pieces, so this has to be // earlier. - for (Partition &Part : Partitions) - finalizeSynthetic(Part.EhFrame); + for (Partition &part : partitions) + finalizeSynthetic(part.ehFrame); - Symtab->forEachSymbol([](Symbol *S) { - if (!S->IsPreemptible) - S->IsPreemptible = computeIsPreemptible(*S); + symtab->forEachSymbol([](Symbol *s) { + if (!s->isPreemptible) + s->isPreemptible = computeIsPreemptible(*s); }); // Scan relocations. This must be done after every symbol is declared so that // we can correctly decide if a dynamic relocation is needed. - if (!Config->Relocatable) { + if (!config->relocatable) { forEachRelSec(scanRelocations); reportUndefinedSymbols(); } addIRelativeRelocs(); - if (In.Plt && In.Plt->isNeeded()) - In.Plt->addSymbols(); - if (In.Iplt && In.Iplt->isNeeded()) - In.Iplt->addSymbols(); + if (in.plt && in.plt->isNeeded()) + in.plt->addSymbols(); + if (in.iplt && in.iplt->isNeeded()) + in.iplt->addSymbols(); - if (!Config->AllowShlibUndefined) { + if (!config->allowShlibUndefined) { // Error on undefined symbols in a shared object, if all of its DT_NEEDED // entires are seen. These cases would otherwise lead to runtime errors // reported by the dynamic linker. @@ -1757,53 +1757,53 @@ // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to // catch more cases. That is too much for us. Our approach resembles the one // used in ld.gold, achieves a good balance to be useful but not too smart. - for (SharedFile *File : SharedFiles) - File->AllNeededIsKnown = - llvm::all_of(File->DtNeeded, [&](StringRef Needed) { - return Symtab->SoNames.count(Needed); + for (SharedFile *file : sharedFiles) + file->allNeededIsKnown = + llvm::all_of(file->dtNeeded, [&](StringRef needed) { + return symtab->soNames.count(needed); }); - Symtab->forEachSymbol([](Symbol *Sym) { - if (Sym->isUndefined() && !Sym->isWeak()) - if (auto *F = dyn_cast_or_null(Sym->File)) - if (F->AllNeededIsKnown) - error(toString(F) + ": undefined reference to " + toString(*Sym)); + symtab->forEachSymbol([](Symbol *sym) { + if (sym->isUndefined() && !sym->isWeak()) + if (auto *f = dyn_cast_or_null(sym->file)) + if (f->allNeededIsKnown) + error(toString(f) + ": undefined reference to " + toString(*sym)); }); } // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. - Symtab->forEachSymbol([](Symbol *Sym) { - if (!includeInSymtab(*Sym)) + symtab->forEachSymbol([](Symbol *sym) { + if (!includeInSymtab(*sym)) return; - if (In.SymTab) - In.SymTab->addSymbol(Sym); + if (in.symTab) + in.symTab->addSymbol(sym); - if (Sym->includeInDynsym()) { - Partitions[Sym->Partition - 1].DynSymTab->addSymbol(Sym); - if (auto *File = dyn_cast_or_null(Sym->File)) - if (File->IsNeeded && !Sym->isUndefined()) - addVerneed(Sym); + if (sym->includeInDynsym()) { + partitions[sym->partition - 1].dynSymTab->addSymbol(sym); + if (auto *file = dyn_cast_or_null(sym->file)) + if (file->isNeeded && !sym->isUndefined()) + addVerneed(sym); } }); // We also need to scan the dynamic relocation tables of the other partitions // and add any referenced symbols to the partition's dynsym. - for (Partition &Part : MutableArrayRef(Partitions).slice(1)) { - DenseSet Syms; - for (const SymbolTableEntry &E : Part.DynSymTab->getSymbols()) - Syms.insert(E.Sym); - for (DynamicReloc &Reloc : Part.RelaDyn->Relocs) - if (Reloc.Sym && !Reloc.UseSymVA && Syms.insert(Reloc.Sym).second) - Part.DynSymTab->addSymbol(Reloc.Sym); + for (Partition &part : MutableArrayRef(partitions).slice(1)) { + DenseSet syms; + for (const SymbolTableEntry &e : part.dynSymTab->getSymbols()) + syms.insert(e.sym); + for (DynamicReloc &reloc : part.relaDyn->relocs) + if (reloc.sym && !reloc.useSymVA && syms.insert(reloc.sym).second) + part.dynSymTab->addSymbol(reloc.sym); } // Do not proceed if there was an undefined symbol. if (errorCount()) return; - if (In.MipsGot) - In.MipsGot->build(); + if (in.mipsGot) + in.mipsGot->build(); removeUnusedSyntheticSections(); @@ -1811,95 +1811,95 @@ // Now that we have the final list, create a list of all the // OutputSections for convenience. - for (BaseCommand *Base : Script->SectionCommands) - if (auto *Sec = dyn_cast(Base)) - OutputSections.push_back(Sec); + for (BaseCommand *base : script->sectionCommands) + if (auto *sec = dyn_cast(base)) + outputSections.push_back(sec); // Prefer command line supplied address over other constraints. - for (OutputSection *Sec : OutputSections) { - auto I = Config->SectionStartMap.find(Sec->Name); - if (I != Config->SectionStartMap.end()) - Sec->AddrExpr = [=] { return I->second; }; + for (OutputSection *sec : outputSections) { + auto i = config->sectionStartMap.find(sec->name); + if (i != config->sectionStartMap.end()) + sec->addrExpr = [=] { return i->second; }; } // This is a bit of a hack. A value of 0 means undef, so we set it // to 1 to make __ehdr_start defined. The section number is not // particularly relevant. - Out::ElfHeader->SectionIndex = 1; + Out::elfHeader->sectionIndex = 1; - for (size_t I = 0, E = OutputSections.size(); I != E; ++I) { - OutputSection *Sec = OutputSections[I]; - Sec->SectionIndex = I + 1; - Sec->ShName = In.ShStrTab->addString(Sec->Name); + for (size_t i = 0, e = outputSections.size(); i != e; ++i) { + OutputSection *sec = outputSections[i]; + sec->sectionIndex = i + 1; + sec->shName = in.shStrTab->addString(sec->name); } // Binary and relocatable output does not have PHDRS. // The headers have to be created before finalize as that can influence the // image base and the dynamic section on mips includes the image base. - if (!Config->Relocatable && !Config->OFormatBinary) { - for (Partition &Part : Partitions) { - Part.Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() - : createPhdrs(Part); - if (Config->EMachine == EM_ARM) { + if (!config->relocatable && !config->oFormatBinary) { + for (Partition &part : partitions) { + part.phdrs = script->hasPhdrsCommands() ? script->createPhdrs() + : createPhdrs(part); + if (config->emachine == EM_ARM) { // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME - addPhdrForSection(Part, SHT_ARM_EXIDX, PT_ARM_EXIDX, PF_R); + addPhdrForSection(part, SHT_ARM_EXIDX, PT_ARM_EXIDX, PF_R); } - if (Config->EMachine == EM_MIPS) { + if (config->emachine == EM_MIPS) { // Add separate segments for MIPS-specific sections. - addPhdrForSection(Part, SHT_MIPS_REGINFO, PT_MIPS_REGINFO, PF_R); - addPhdrForSection(Part, SHT_MIPS_OPTIONS, PT_MIPS_OPTIONS, PF_R); - addPhdrForSection(Part, SHT_MIPS_ABIFLAGS, PT_MIPS_ABIFLAGS, PF_R); + addPhdrForSection(part, SHT_MIPS_REGINFO, PT_MIPS_REGINFO, PF_R); + addPhdrForSection(part, SHT_MIPS_OPTIONS, PT_MIPS_OPTIONS, PF_R); + addPhdrForSection(part, SHT_MIPS_ABIFLAGS, PT_MIPS_ABIFLAGS, PF_R); } } - Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Main->Phdrs.size(); + Out::programHeaders->size = sizeof(Elf_Phdr) * mainPart->phdrs.size(); // Find the TLS segment. This happens before the section layout loop so that // Android relocation packing can look up TLS symbol addresses. We only need // to care about the main partition here because all TLS symbols were moved // to the main partition (see MarkLive.cpp). - for (PhdrEntry *P : Main->Phdrs) - if (P->p_type == PT_TLS) - Out::TlsPhdr = P; + for (PhdrEntry *p : mainPart->phdrs) + if (p->p_type == PT_TLS) + Out::tlsPhdr = p; } // Some symbols are defined in term of program headers. Now that we // have the headers, we can find out which sections they point to. setReservedSymbolSections(); - finalizeSynthetic(In.Bss); - finalizeSynthetic(In.BssRelRo); - finalizeSynthetic(In.SymTabShndx); - finalizeSynthetic(In.ShStrTab); - finalizeSynthetic(In.StrTab); - finalizeSynthetic(In.Got); - finalizeSynthetic(In.MipsGot); - finalizeSynthetic(In.IgotPlt); - finalizeSynthetic(In.GotPlt); - finalizeSynthetic(In.RelaIplt); - finalizeSynthetic(In.RelaPlt); - finalizeSynthetic(In.Plt); - finalizeSynthetic(In.Iplt); - finalizeSynthetic(In.PPC32Got2); - finalizeSynthetic(In.RISCVSdata); - finalizeSynthetic(In.PartIndex); + finalizeSynthetic(in.bss); + finalizeSynthetic(in.bssRelRo); + finalizeSynthetic(in.symTabShndx); + finalizeSynthetic(in.shStrTab); + finalizeSynthetic(in.strTab); + finalizeSynthetic(in.got); + finalizeSynthetic(in.mipsGot); + finalizeSynthetic(in.igotPlt); + finalizeSynthetic(in.gotPlt); + finalizeSynthetic(in.relaIplt); + finalizeSynthetic(in.relaPlt); + finalizeSynthetic(in.plt); + finalizeSynthetic(in.iplt); + finalizeSynthetic(in.ppc32Got2); + finalizeSynthetic(in.riscvSdata); + finalizeSynthetic(in.partIndex); // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. - for (Partition &Part : Partitions) { - finalizeSynthetic(Part.ARMExidx); - finalizeSynthetic(Part.DynSymTab); - finalizeSynthetic(Part.GnuHashTab); - finalizeSynthetic(Part.HashTab); - finalizeSynthetic(Part.VerDef); - finalizeSynthetic(Part.RelaDyn); - finalizeSynthetic(Part.RelrDyn); - finalizeSynthetic(Part.EhFrameHdr); - finalizeSynthetic(Part.VerSym); - finalizeSynthetic(Part.VerNeed); - finalizeSynthetic(Part.Dynamic); + for (Partition &part : partitions) { + finalizeSynthetic(part.armExidx); + finalizeSynthetic(part.dynSymTab); + finalizeSynthetic(part.gnuHashTab); + finalizeSynthetic(part.hashTab); + finalizeSynthetic(part.verDef); + finalizeSynthetic(part.relaDyn); + finalizeSynthetic(part.relrDyn); + finalizeSynthetic(part.ehFrameHdr); + finalizeSynthetic(part.verSym); + finalizeSynthetic(part.verNeed); + finalizeSynthetic(part.dynamic); } - if (!Script->HasSectionsCommand && !Config->Relocatable) + if (!script->hasSectionsCommand && !config->relocatable) fixSectionAlignments(); // SHFLinkOrder processing must be processed after relative section placements are @@ -1930,28 +1930,28 @@ finalizeAddressDependentContent(); // finalizeAddressDependentContent may have added local symbols to the static symbol table. - finalizeSynthetic(In.SymTab); - finalizeSynthetic(In.PPC64LongBranchTarget); + finalizeSynthetic(in.symTab); + finalizeSynthetic(in.ppc64LongBranchTarget); // Fill other section headers. The dynamic table is finalized // at the end because some tags like RELSZ depend on result // of finalizing other sections. - for (OutputSection *Sec : OutputSections) - Sec->finalize(); + for (OutputSection *sec : outputSections) + sec->finalize(); } // Ensure data sections are not mixed with executable sections when // -execute-only is used. -execute-only is a feature to make pages executable // but not readable, and the feature is currently supported only on AArch64. template void Writer::checkExecuteOnly() { - if (!Config->ExecuteOnly) + if (!config->executeOnly) return; - for (OutputSection *OS : OutputSections) - if (OS->Flags & SHF_EXECINSTR) - for (InputSection *IS : getInputSections(OS)) - if (!(IS->Flags & SHF_EXECINSTR)) - error("cannot place " + toString(IS) + " into " + toString(OS->Name) + + for (OutputSection *os : outputSections) + if (os->flags & SHF_EXECINSTR) + for (InputSection *isec : getInputSections(os)) + if (!(isec->flags & SHF_EXECINSTR)) + error("cannot place " + toString(isec) + " into " + toString(os->name) + ": -execute-only does not support intermingling data and code"); } @@ -1976,24 +1976,24 @@ // case, use the image base address as a last resort. OutputSection *Default = findSection(".text"); if (!Default) - Default = Out::ElfHeader; + Default = Out::elfHeader; - auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) { - if (OS) { - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, -1); + auto define = [=](StringRef start, StringRef end, OutputSection *os) { + if (os) { + addOptionalRegular(start, os, 0); + addOptionalRegular(end, os, -1); } else { - addOptionalRegular(Start, Default, 0); - addOptionalRegular(End, Default, 0); + addOptionalRegular(start, Default, 0); + addOptionalRegular(end, Default, 0); } }; - Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray); - Define("__init_array_start", "__init_array_end", Out::InitArray); - Define("__fini_array_start", "__fini_array_end", Out::FiniArray); + define("__preinit_array_start", "__preinit_array_end", Out::preinitArray); + define("__init_array_start", "__init_array_end", Out::initArray); + define("__fini_array_start", "__fini_array_end", Out::finiArray); - if (OutputSection *Sec = findSection(".ARM.exidx")) - Define("__exidx_start", "__exidx_end", Sec); + if (OutputSection *sec = findSection(".ARM.exidx")) + define("__exidx_start", "__exidx_end", sec); } // If a section name is valid as a C identifier (which is rare because of @@ -2002,22 +2002,22 @@ // respectively. This is not requested by the ELF standard, but GNU ld and // gold provide the feature, and used by many programs. template -void Writer::addStartStopSymbols(OutputSection *Sec) { - StringRef S = Sec->Name; - if (!isValidCIdentifier(S)) +void Writer::addStartStopSymbols(OutputSection *sec) { + StringRef s = sec->name; + if (!isValidCIdentifier(s)) return; - addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_PROTECTED); - addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_PROTECTED); + addOptionalRegular(Saver.save("__start_" + s), sec, 0, STV_PROTECTED); + addOptionalRegular(Saver.save("__stop_" + s), sec, -1, STV_PROTECTED); } -static bool needsPtLoad(OutputSection *Sec) { - if (!(Sec->Flags & SHF_ALLOC) || Sec->Noload) +static bool needsPtLoad(OutputSection *sec) { + if (!(sec->flags & SHF_ALLOC) || sec->noload) return false; // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is // responsible for allocating space for them, not the PT_LOAD that // contains the TLS initialization image. - if ((Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS) + if ((sec->flags & SHF_TLS) && sec->type == SHT_NOBITS) return false; return true; } @@ -2026,79 +2026,79 @@ // linker scripts are designed for creating two PT_LOADs only, one RX and one // RW. This means that there is no alignment in the RO to RX transition and we // cannot create a PT_LOAD there. -static uint64_t computeFlags(uint64_t Flags) { - if (Config->Omagic) +static uint64_t computeFlags(uint64_t flags) { + if (config->omagic) return PF_R | PF_W | PF_X; - if (Config->ExecuteOnly && (Flags & PF_X)) - return Flags & ~PF_R; - if (Config->SingleRoRx && !(Flags & PF_W)) - return Flags | PF_X; - return Flags; + if (config->executeOnly && (flags & PF_X)) + return flags & ~PF_R; + if (config->singleRoRx && !(flags & PF_W)) + return flags | PF_X; + return flags; } // Decide which program headers to create and which sections to include in each // one. template -std::vector Writer::createPhdrs(Partition &Part) { - std::vector Ret; - auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * { - Ret.push_back(make(Type, Flags)); - return Ret.back(); +std::vector Writer::createPhdrs(Partition &part) { + std::vector ret; + auto addHdr = [&](unsigned type, unsigned flags) -> PhdrEntry * { + ret.push_back(make(type, flags)); + return ret.back(); }; - unsigned PartNo = Part.getNumber(); - bool IsMain = PartNo == 1; + unsigned partNo = part.getNumber(); + bool isMain = partNo == 1; // The first phdr entry is PT_PHDR which describes the program header itself. - if (IsMain) - AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders); + if (isMain) + addHdr(PT_PHDR, PF_R)->add(Out::programHeaders); else - AddHdr(PT_PHDR, PF_R)->add(Part.ProgramHeaders->getParent()); + addHdr(PT_PHDR, PF_R)->add(part.programHeaders->getParent()); // PT_INTERP must be the second entry if exists. - if (OutputSection *Cmd = findSection(".interp", PartNo)) - AddHdr(PT_INTERP, Cmd->getPhdrFlags())->add(Cmd); + if (OutputSection *cmd = findSection(".interp", partNo)) + addHdr(PT_INTERP, cmd->getPhdrFlags())->add(cmd); // Add the first PT_LOAD segment for regular output sections. - uint64_t Flags = computeFlags(PF_R); - PhdrEntry *Load = nullptr; + uint64_t flags = computeFlags(PF_R); + PhdrEntry *load = nullptr; // Add the headers. We will remove them if they don't fit. // In the other partitions the headers are ordinary sections, so they don't // need to be added here. - if (IsMain) { - Load = AddHdr(PT_LOAD, Flags); - Load->add(Out::ElfHeader); - Load->add(Out::ProgramHeaders); + if (isMain) { + load = addHdr(PT_LOAD, flags); + load->add(Out::elfHeader); + load->add(Out::programHeaders); } // PT_GNU_RELRO includes all sections that should be marked as // read-only by dynamic linker after proccessing relocations. // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give // an error message if more than one PT_GNU_RELRO PHDR is required. - PhdrEntry *RelRo = make(PT_GNU_RELRO, PF_R); - bool InRelroPhdr = false; - OutputSection *RelroEnd = nullptr; - for (OutputSection *Sec : OutputSections) { - if (Sec->Partition != PartNo || !needsPtLoad(Sec)) + PhdrEntry *relRo = make(PT_GNU_RELRO, PF_R); + bool inRelroPhdr = false; + OutputSection *relroEnd = nullptr; + for (OutputSection *sec : outputSections) { + if (sec->partition != partNo || !needsPtLoad(sec)) continue; - if (isRelroSection(Sec)) { - InRelroPhdr = true; - if (!RelroEnd) - RelRo->add(Sec); + if (isRelroSection(sec)) { + inRelroPhdr = true; + if (!relroEnd) + relRo->add(sec); else - error("section: " + Sec->Name + " is not contiguous with other relro" + + error("section: " + sec->name + " is not contiguous with other relro" + " sections"); - } else if (InRelroPhdr) { - InRelroPhdr = false; - RelroEnd = Sec; + } else if (inRelroPhdr) { + inRelroPhdr = false; + relroEnd = sec; } } - for (OutputSection *Sec : OutputSections) { - if (!(Sec->Flags & SHF_ALLOC)) + for (OutputSection *sec : outputSections) { + if (!(sec->flags & SHF_ALLOC)) break; - if (!needsPtLoad(Sec)) + if (!needsPtLoad(sec)) continue; // Normally, sections in partitions other than the current partition are @@ -2107,9 +2107,9 @@ // partition so that a segment is created for it in the main partition, // which will cause the dynamic loader to reserve space for the other // partitions. - if (Sec->Partition != PartNo) { - if (IsMain && Sec->Partition == 255) - AddHdr(PT_LOAD, computeFlags(Sec->getPhdrFlags()))->add(Sec); + if (sec->partition != partNo) { + if (isMain && sec->partition == 255) + addHdr(PT_LOAD, computeFlags(sec->getPhdrFlags()))->add(sec); continue; } @@ -2120,127 +2120,127 @@ // region using AT or AT> linker script command, respectively. At the same // time, we don't want to create a separate load segment for the headers, // even if the first output section has an AT or AT> attribute. - uint64_t NewFlags = computeFlags(Sec->getPhdrFlags()); - if (!Load || - ((Sec->LMAExpr || - (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) && - Load->LastSec != Out::ProgramHeaders) || - Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags || - Sec == RelroEnd) { - Load = AddHdr(PT_LOAD, NewFlags); - Flags = NewFlags; + uint64_t newFlags = computeFlags(sec->getPhdrFlags()); + if (!load || + ((sec->lmaExpr || + (sec->lmaRegion && (sec->lmaRegion != load->firstSec->lmaRegion))) && + load->lastSec != Out::programHeaders) || + sec->memRegion != load->firstSec->memRegion || flags != newFlags || + sec == relroEnd) { + load = addHdr(PT_LOAD, newFlags); + flags = newFlags; } - Load->add(Sec); + load->add(sec); } // Add a TLS segment if any. - PhdrEntry *TlsHdr = make(PT_TLS, PF_R); - for (OutputSection *Sec : OutputSections) - if (Sec->Partition == PartNo && Sec->Flags & SHF_TLS) - TlsHdr->add(Sec); - if (TlsHdr->FirstSec) - Ret.push_back(TlsHdr); + PhdrEntry *tlsHdr = make(PT_TLS, PF_R); + for (OutputSection *sec : outputSections) + if (sec->partition == partNo && sec->flags & SHF_TLS) + tlsHdr->add(sec); + if (tlsHdr->firstSec) + ret.push_back(tlsHdr); // Add an entry for .dynamic. - if (OutputSection *Sec = Part.Dynamic->getParent()) - AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec); + if (OutputSection *sec = part.dynamic->getParent()) + addHdr(PT_DYNAMIC, sec->getPhdrFlags())->add(sec); - if (RelRo->FirstSec) - Ret.push_back(RelRo); + if (relRo->firstSec) + ret.push_back(relRo); // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. - if (Part.EhFrame->isNeeded() && Part.EhFrameHdr && - Part.EhFrame->getParent() && Part.EhFrameHdr->getParent()) - AddHdr(PT_GNU_EH_FRAME, Part.EhFrameHdr->getParent()->getPhdrFlags()) - ->add(Part.EhFrameHdr->getParent()); + if (part.ehFrame->isNeeded() && part.ehFrameHdr && + part.ehFrame->getParent() && part.ehFrameHdr->getParent()) + addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags()) + ->add(part.ehFrameHdr->getParent()); // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes // the dynamic linker fill the segment with random data. - if (OutputSection *Cmd = findSection(".openbsd.randomdata", PartNo)) - AddHdr(PT_OPENBSD_RANDOMIZE, Cmd->getPhdrFlags())->add(Cmd); + if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo)) + addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd); // PT_GNU_STACK is a special section to tell the loader to make the // pages for the stack non-executable. If you really want an executable // stack, you can pass -z execstack, but that's not recommended for // security reasons. - unsigned Perm = PF_R | PF_W; - if (Config->ZExecstack) - Perm |= PF_X; - AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize; + unsigned perm = PF_R | PF_W; + if (config->zExecstack) + perm |= PF_X; + addHdr(PT_GNU_STACK, perm)->p_memsz = config->zStackSize; // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable // is expected to perform W^X violations, such as calling mprotect(2) or // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on // OpenBSD. - if (Config->ZWxneeded) - AddHdr(PT_OPENBSD_WXNEEDED, PF_X); + if (config->zWxneeded) + addHdr(PT_OPENBSD_WXNEEDED, PF_X); // Create one PT_NOTE per a group of contiguous SHT_NOTE sections with the // same alignment. - PhdrEntry *Note = nullptr; - for (OutputSection *Sec : OutputSections) { - if (Sec->Partition != PartNo) + PhdrEntry *note = nullptr; + for (OutputSection *sec : outputSections) { + if (sec->partition != partNo) continue; - if (Sec->Type == SHT_NOTE && (Sec->Flags & SHF_ALLOC)) { - if (!Note || Sec->LMAExpr || Note->LastSec->Alignment != Sec->Alignment) - Note = AddHdr(PT_NOTE, PF_R); - Note->add(Sec); + if (sec->type == SHT_NOTE && (sec->flags & SHF_ALLOC)) { + if (!note || sec->lmaExpr || note->lastSec->alignment != sec->alignment) + note = addHdr(PT_NOTE, PF_R); + note->add(sec); } else { - Note = nullptr; + note = nullptr; } } - return Ret; + return ret; } template -void Writer::addPhdrForSection(Partition &Part, unsigned ShType, - unsigned PType, unsigned PFlags) { - unsigned PartNo = Part.getNumber(); - auto I = llvm::find_if(OutputSections, [=](OutputSection *Cmd) { - return Cmd->Partition == PartNo && Cmd->Type == ShType; +void Writer::addPhdrForSection(Partition &part, unsigned shType, + unsigned pType, unsigned pFlags) { + unsigned partNo = part.getNumber(); + auto i = llvm::find_if(outputSections, [=](OutputSection *cmd) { + return cmd->partition == partNo && cmd->type == shType; }); - if (I == OutputSections.end()) + if (i == outputSections.end()) return; - PhdrEntry *Entry = make(PType, PFlags); - Entry->add(*I); - Part.Phdrs.push_back(Entry); + PhdrEntry *entry = make(pType, pFlags); + entry->add(*i); + part.phdrs.push_back(entry); } // The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the // first section after PT_GNU_RELRO have to be page aligned so that the dynamic // linker can set the permissions. template void Writer::fixSectionAlignments() { - auto PageAlign = [](OutputSection *Cmd) { - if (Cmd && !Cmd->AddrExpr) - Cmd->AddrExpr = [=] { - return alignTo(Script->getDot(), Config->MaxPageSize); + auto pageAlign = [](OutputSection *cmd) { + if (cmd && !cmd->addrExpr) + cmd->addrExpr = [=] { + return alignTo(script->getDot(), config->maxPageSize); }; }; - for (Partition &Part : Partitions) { - for (const PhdrEntry *P : Part.Phdrs) - if (P->p_type == PT_LOAD && P->FirstSec) - PageAlign(P->FirstSec); + for (Partition &part : partitions) { + for (const PhdrEntry *p : part.phdrs) + if (p->p_type == PT_LOAD && p->firstSec) + pageAlign(p->firstSec); - for (const PhdrEntry *P : Part.Phdrs) { - if (P->p_type != PT_GNU_RELRO) + for (const PhdrEntry *p : part.phdrs) { + if (p->p_type != PT_GNU_RELRO) continue; - if (P->FirstSec) - PageAlign(P->FirstSec); + if (p->firstSec) + pageAlign(p->firstSec); // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we // have to align it to a page. - auto End = OutputSections.end(); - auto I = llvm::find(OutputSections, P->LastSec); - if (I == End || (I + 1) == End) + auto end = outputSections.end(); + auto i = llvm::find(outputSections, p->lastSec); + if (i == end || (i + 1) == end) continue; - OutputSection *Cmd = (*(I + 1)); - if (needsPtLoad(Cmd)) - PageAlign(Cmd); + OutputSection *cmd = (*(i + 1)); + if (needsPtLoad(cmd)) + pageAlign(cmd); } } } @@ -2248,78 +2248,78 @@ // Compute an in-file position for a given section. The file offset must be the // same with its virtual address modulo the page size, so that the loader can // load executables without any address adjustment. -static uint64_t computeFileOffset(OutputSection *OS, uint64_t Off) { +static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { // File offsets are not significant for .bss sections. By convention, we keep // section offsets monotonically increasing rather than setting to zero. - if (OS->Type == SHT_NOBITS) - return Off; + if (os->type == SHT_NOBITS) + return off; // If the section is not in a PT_LOAD, we just have to align it. - if (!OS->PtLoad) - return alignTo(Off, OS->Alignment); + if (!os->ptLoad) + return alignTo(off, os->alignment); // The first section in a PT_LOAD has to have congruent offset and address // module the page size. - OutputSection *First = OS->PtLoad->FirstSec; - if (OS == First) { - uint64_t Alignment = std::max(OS->Alignment, Config->MaxPageSize); - return alignTo(Off, Alignment, OS->Addr); + OutputSection *first = os->ptLoad->firstSec; + if (os == first) { + uint64_t alignment = std::max(os->alignment, config->maxPageSize); + return alignTo(off, alignment, os->addr); } // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). - return First->Offset + OS->Addr - First->Addr; + return first->offset + os->addr - first->addr; } // Set an in-file position to a given section and returns the end position of // the section. -static uint64_t setFileOffset(OutputSection *OS, uint64_t Off) { - Off = computeFileOffset(OS, Off); - OS->Offset = Off; - - if (OS->Type == SHT_NOBITS) - return Off; - return Off + OS->Size; +static uint64_t setFileOffset(OutputSection *os, uint64_t off) { + off = computeFileOffset(os, off); + os->offset = off; + + if (os->type == SHT_NOBITS) + return off; + return off + os->size; } template void Writer::assignFileOffsetsBinary() { - uint64_t Off = 0; - for (OutputSection *Sec : OutputSections) - if (Sec->Flags & SHF_ALLOC) - Off = setFileOffset(Sec, Off); - FileSize = alignTo(Off, Config->Wordsize); + uint64_t off = 0; + for (OutputSection *sec : outputSections) + if (sec->flags & SHF_ALLOC) + off = setFileOffset(sec, off); + fileSize = alignTo(off, config->wordsize); } -static std::string rangeToString(uint64_t Addr, uint64_t Len) { - return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]"; +static std::string rangeToString(uint64_t addr, uint64_t len) { + return "[0x" + utohexstr(addr) + ", 0x" + utohexstr(addr + len - 1) + "]"; } // Assign file offsets to output sections. template void Writer::assignFileOffsets() { - uint64_t Off = 0; - Off = setFileOffset(Out::ElfHeader, Off); - Off = setFileOffset(Out::ProgramHeaders, Off); - - PhdrEntry *LastRX = nullptr; - for (Partition &Part : Partitions) - for (PhdrEntry *P : Part.Phdrs) - if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) - LastRX = P; - - for (OutputSection *Sec : OutputSections) { - Off = setFileOffset(Sec, Off); - if (Script->HasSectionsCommand) + uint64_t off = 0; + off = setFileOffset(Out::elfHeader, off); + off = setFileOffset(Out::programHeaders, off); + + PhdrEntry *lastRX = nullptr; + for (Partition &part : partitions) + for (PhdrEntry *p : part.phdrs) + if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) + lastRX = p; + + for (OutputSection *sec : outputSections) { + off = setFileOffset(sec, off); + if (script->hasSectionsCommand) continue; // If this is a last section of the last executable segment and that // segment is the last loadable segment, align the offset of the // following section to avoid loading non-segments parts of the file. - if (LastRX && LastRX->LastSec == Sec) - Off = alignTo(Off, Config->CommonPageSize); + if (lastRX && lastRX->lastSec == sec) + off = alignTo(off, config->commonPageSize); } - SectionHeaderOff = alignTo(Off, Config->Wordsize); - FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); + sectionHeaderOff = alignTo(off, config->wordsize); + fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr); // Our logic assumes that sections have rising VA within the same segment. // With use of linker scripts it is possible to violate this rule and get file @@ -2330,49 +2330,49 @@ // backwards, so we have to allow doing that to support linking them. We // perform non-critical checks for overlaps in checkSectionOverlap(), but here // we want to prevent file size overflows because it would crash the linker. - for (OutputSection *Sec : OutputSections) { - if (Sec->Type == SHT_NOBITS) + for (OutputSection *sec : outputSections) { + if (sec->type == SHT_NOBITS) continue; - if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize)) - error("unable to place section " + Sec->Name + " at file offset " + - rangeToString(Sec->Offset, Sec->Size) + + if ((sec->offset > fileSize) || (sec->offset + sec->size > fileSize)) + error("unable to place section " + sec->name + " at file offset " + + rangeToString(sec->offset, sec->size) + "; check your linker script for overflows"); } } // Finalize the program headers. We call this function after we assign // file offsets and VAs to all sections. -template void Writer::setPhdrs(Partition &Part) { - for (PhdrEntry *P : Part.Phdrs) { - OutputSection *First = P->FirstSec; - OutputSection *Last = P->LastSec; - - if (First) { - P->p_filesz = Last->Offset - First->Offset; - if (Last->Type != SHT_NOBITS) - P->p_filesz += Last->Size; - - P->p_memsz = Last->Addr + Last->Size - First->Addr; - P->p_offset = First->Offset; - P->p_vaddr = First->Addr; +template void Writer::setPhdrs(Partition &part) { + for (PhdrEntry *p : part.phdrs) { + OutputSection *first = p->firstSec; + OutputSection *last = p->lastSec; + + if (first) { + p->p_filesz = last->offset - first->offset; + if (last->type != SHT_NOBITS) + p->p_filesz += last->size; + + p->p_memsz = last->addr + last->size - first->addr; + p->p_offset = first->offset; + p->p_vaddr = first->addr; // File offsets in partitions other than the main partition are relative // to the offset of the ELF headers. Perform that adjustment now. - if (Part.ElfHeader) - P->p_offset -= Part.ElfHeader->getParent()->Offset; + if (part.elfHeader) + p->p_offset -= part.elfHeader->getParent()->offset; - if (!P->HasLMA) - P->p_paddr = First->getLMA(); + if (!p->hasLMA) + p->p_paddr = first->getLMA(); } - if (P->p_type == PT_LOAD) { - P->p_align = std::max(P->p_align, Config->MaxPageSize); - } else if (P->p_type == PT_GNU_RELRO) { - P->p_align = 1; + if (p->p_type == PT_LOAD) { + p->p_align = std::max(p->p_align, config->maxPageSize); + } else if (p->p_type == PT_GNU_RELRO) { + p->p_align = 1; // The glibc dynamic loader rounds the size down, so we need to round up // to protect the last page. This is a no-op on FreeBSD which always // rounds up. - P->p_memsz = alignTo(P->p_memsz, Config->CommonPageSize); + p->p_memsz = alignTo(p->p_memsz, config->commonPageSize); } } } @@ -2380,37 +2380,37 @@ // A helper struct for checkSectionOverlap. namespace { struct SectionOffset { - OutputSection *Sec; - uint64_t Offset; + OutputSection *sec; + uint64_t offset; }; } // namespace // Check whether sections overlap for a specific address range (file offsets, // load and virtual adresses). -static void checkOverlap(StringRef Name, std::vector &Sections, - bool IsVirtualAddr) { - llvm::sort(Sections, [=](const SectionOffset &A, const SectionOffset &B) { - return A.Offset < B.Offset; +static void checkOverlap(StringRef name, std::vector §ions, + bool isVirtualAddr) { + llvm::sort(sections, [=](const SectionOffset &a, const SectionOffset &b) { + return a.offset < b.offset; }); // Finding overlap is easy given a vector is sorted by start position. // If an element starts before the end of the previous element, they overlap. - for (size_t I = 1, End = Sections.size(); I < End; ++I) { - SectionOffset A = Sections[I - 1]; - SectionOffset B = Sections[I]; - if (B.Offset >= A.Offset + A.Sec->Size) + for (size_t i = 1, end = sections.size(); i < end; ++i) { + SectionOffset a = sections[i - 1]; + SectionOffset b = sections[i]; + if (b.offset >= a.offset + a.sec->size) continue; // If both sections are in OVERLAY we allow the overlapping of virtual // addresses, because it is what OVERLAY was designed for. - if (IsVirtualAddr && A.Sec->InOverlay && B.Sec->InOverlay) + if (isVirtualAddr && a.sec->inOverlay && b.sec->inOverlay) continue; - errorOrWarn("section " + A.Sec->Name + " " + Name + - " range overlaps with " + B.Sec->Name + "\n>>> " + A.Sec->Name + - " range is " + rangeToString(A.Offset, A.Sec->Size) + "\n>>> " + - B.Sec->Name + " range is " + - rangeToString(B.Offset, B.Sec->Size)); + errorOrWarn("section " + a.sec->name + " " + name + + " range overlaps with " + b.sec->name + "\n>>> " + a.sec->name + + " range is " + rangeToString(a.offset, a.sec->size) + "\n>>> " + + b.sec->name + " range is " + + rangeToString(b.offset, b.sec->size)); } } @@ -2421,11 +2421,11 @@ // ranges and the virtual address ranges don't overlap template void Writer::checkSections() { // First, check that section's VAs fit in available address space for target. - for (OutputSection *OS : OutputSections) - if ((OS->Addr + OS->Size < OS->Addr) || - (!ELFT::Is64Bits && OS->Addr + OS->Size > UINT32_MAX)) - errorOrWarn("section " + OS->Name + " at 0x" + utohexstr(OS->Addr) + - " of size 0x" + utohexstr(OS->Size) + + for (OutputSection *os : outputSections) + if ((os->addr + os->size < os->addr) || + (!ELFT::Is64Bits && os->addr + os->size > UINT32_MAX)) + errorOrWarn("section " + os->name + " at 0x" + utohexstr(os->addr) + + " of size 0x" + utohexstr(os->size) + " exceeds available address space"); // Check for overlapping file offsets. In this case we need to skip any @@ -2433,17 +2433,17 @@ // the file so Sec->Offset + Sec->Size can overlap with others. If --oformat // binary is specified only add SHF_ALLOC sections are added to the output // file so we skip any non-allocated sections in that case. - std::vector FileOffs; - for (OutputSection *Sec : OutputSections) - if (Sec->Size > 0 && Sec->Type != SHT_NOBITS && - (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC))) - FileOffs.push_back({Sec, Sec->Offset}); - checkOverlap("file", FileOffs, false); + std::vector fileOffs; + for (OutputSection *sec : outputSections) + if (sec->size > 0 && sec->type != SHT_NOBITS && + (!config->oFormatBinary || (sec->flags & SHF_ALLOC))) + fileOffs.push_back({sec, sec->offset}); + checkOverlap("file", fileOffs, false); // When linking with -r there is no need to check for overlapping virtual/load // addresses since those addresses will only be assigned when the final // executable/shared object is created. - if (Config->Relocatable) + if (config->relocatable) return; // Checking for overlapping virtual and load addresses only needs to take @@ -2451,20 +2451,20 @@ // Furthermore, we also need to skip SHF_TLS sections since these will be // mapped to other addresses at runtime and can therefore have overlapping // ranges in the file. - std::vector VMAs; - for (OutputSection *Sec : OutputSections) - if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) - VMAs.push_back({Sec, Sec->Addr}); - checkOverlap("virtual address", VMAs, true); + std::vector vmas; + for (OutputSection *sec : outputSections) + if (sec->size > 0 && (sec->flags & SHF_ALLOC) && !(sec->flags & SHF_TLS)) + vmas.push_back({sec, sec->addr}); + checkOverlap("virtual address", vmas, true); // Finally, check that the load addresses don't overlap. This will usually be // the same as the virtual addresses but can be different when using a linker // script with AT(). - std::vector LMAs; - for (OutputSection *Sec : OutputSections) - if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) - LMAs.push_back({Sec, Sec->getLMA()}); - checkOverlap("load address", LMAs, false); + std::vector lmas; + for (OutputSection *sec : outputSections) + if (sec->size > 0 && (sec->flags & SHF_ALLOC) && !(sec->flags & SHF_TLS)) + lmas.push_back({sec, sec->getLMA()}); + checkOverlap("load address", lmas, false); } // The entry point address is chosen in the following ways. @@ -2477,45 +2477,45 @@ // 6. the address 0. static uint64_t getEntryAddr() { // Case 1, 2 or 3 - if (Symbol *B = Symtab->find(Config->Entry)) - return B->getVA(); + if (Symbol *b = symtab->find(config->entry)) + return b->getVA(); // Case 4 - uint64_t Addr; - if (to_integer(Config->Entry, Addr)) - return Addr; + uint64_t addr; + if (to_integer(config->entry, addr)) + return addr; // Case 5 - if (OutputSection *Sec = findSection(".text")) { - if (Config->WarnMissingEntry) - warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" + - utohexstr(Sec->Addr)); - return Sec->Addr; + if (OutputSection *sec = findSection(".text")) { + if (config->warnMissingEntry) + warn("cannot find entry symbol " + config->entry + "; defaulting to 0x" + + utohexstr(sec->addr)); + return sec->addr; } // Case 6 - if (Config->WarnMissingEntry) - warn("cannot find entry symbol " + Config->Entry + + if (config->warnMissingEntry) + warn("cannot find entry symbol " + config->entry + "; not setting start address"); return 0; } static uint16_t getELFType() { - if (Config->Pic) + if (config->isPic) return ET_DYN; - if (Config->Relocatable) + if (config->relocatable) return ET_REL; return ET_EXEC; } template void Writer::writeHeader() { - writeEhdr(Out::BufferStart, *Main); - writePhdrs(Out::BufferStart + sizeof(Elf_Ehdr), *Main); + writeEhdr(Out::bufferStart, *mainPart); + writePhdrs(Out::bufferStart + sizeof(Elf_Ehdr), *mainPart); - auto *EHdr = reinterpret_cast(Out::BufferStart); - EHdr->e_type = getELFType(); - EHdr->e_entry = getEntryAddr(); - EHdr->e_shoff = SectionHeaderOff; + auto *eHdr = reinterpret_cast(Out::bufferStart); + eHdr->e_type = getELFType(); + eHdr->e_entry = getEntryAddr(); + eHdr->e_shoff = sectionHeaderOff; // Write the section header table. // @@ -2526,58 +2526,58 @@ // the value. The sentinel values and fields are: // e_shnum = 0, SHdrs[0].sh_size = number of sections. // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index. - auto *SHdrs = reinterpret_cast(Out::BufferStart + EHdr->e_shoff); - size_t Num = OutputSections.size() + 1; - if (Num >= SHN_LORESERVE) - SHdrs->sh_size = Num; + auto *sHdrs = reinterpret_cast(Out::bufferStart + eHdr->e_shoff); + size_t num = outputSections.size() + 1; + if (num >= SHN_LORESERVE) + sHdrs->sh_size = num; else - EHdr->e_shnum = Num; + eHdr->e_shnum = num; - uint32_t StrTabIndex = In.ShStrTab->getParent()->SectionIndex; - if (StrTabIndex >= SHN_LORESERVE) { - SHdrs->sh_link = StrTabIndex; - EHdr->e_shstrndx = SHN_XINDEX; + uint32_t strTabIndex = in.shStrTab->getParent()->sectionIndex; + if (strTabIndex >= SHN_LORESERVE) { + sHdrs->sh_link = strTabIndex; + eHdr->e_shstrndx = SHN_XINDEX; } else { - EHdr->e_shstrndx = StrTabIndex; + eHdr->e_shstrndx = strTabIndex; } - for (OutputSection *Sec : OutputSections) - Sec->writeHeaderTo(++SHdrs); + for (OutputSection *sec : outputSections) + sec->writeHeaderTo(++sHdrs); } // Open a result file. template void Writer::openFile() { - uint64_t MaxSize = Config->Is64 ? INT64_MAX : UINT32_MAX; - if (FileSize != size_t(FileSize) || MaxSize < FileSize) { - error("output file too large: " + Twine(FileSize) + " bytes"); + uint64_t maxSize = config->is64 ? INT64_MAX : UINT32_MAX; + if (fileSize != size_t(fileSize) || maxSize < fileSize) { + error("output file too large: " + Twine(fileSize) + " bytes"); return; } - unlinkAsync(Config->OutputFile); - unsigned Flags = 0; - if (!Config->Relocatable) - Flags = FileOutputBuffer::F_executable; - Expected> BufferOrErr = - FileOutputBuffer::create(Config->OutputFile, FileSize, Flags); + unlinkAsync(config->outputFile); + unsigned flags = 0; + if (!config->relocatable) + flags = FileOutputBuffer::F_executable; + Expected> bufferOrErr = + FileOutputBuffer::create(config->outputFile, fileSize, flags); - if (!BufferOrErr) { - error("failed to open " + Config->OutputFile + ": " + - llvm::toString(BufferOrErr.takeError())); + if (!bufferOrErr) { + error("failed to open " + config->outputFile + ": " + + llvm::toString(bufferOrErr.takeError())); return; } - Buffer = std::move(*BufferOrErr); - Out::BufferStart = Buffer->getBufferStart(); + buffer = std::move(*bufferOrErr); + Out::bufferStart = buffer->getBufferStart(); } template void Writer::writeSectionsBinary() { - for (OutputSection *Sec : OutputSections) - if (Sec->Flags & SHF_ALLOC) - Sec->writeTo(Out::BufferStart + Sec->Offset); + for (OutputSection *sec : outputSections) + if (sec->flags & SHF_ALLOC) + sec->writeTo(Out::bufferStart + sec->offset); } -static void fillTrap(uint8_t *I, uint8_t *End) { - for (; I + 4 <= End; I += 4) - memcpy(I, &Target->TrapInstr, 4); +static void fillTrap(uint8_t *i, uint8_t *end) { + for (; i + 4 <= end; i += 4) + memcpy(i, &target->trapInstr, 4); } // Fill the last page of executable segments with trap instructions @@ -2587,29 +2587,29 @@ // We'll leave other pages in segments as-is because the rest will be // overwritten by output sections. template void Writer::writeTrapInstr() { - if (Script->HasSectionsCommand) + if (script->hasSectionsCommand) return; - for (Partition &Part : Partitions) { + for (Partition &part : partitions) { // Fill the last page. - for (PhdrEntry *P : Part.Phdrs) - if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) - fillTrap(Out::BufferStart + alignDown(P->FirstSec->Offset + P->p_filesz, - Config->CommonPageSize), - Out::BufferStart + alignTo(P->FirstSec->Offset + P->p_filesz, - Config->CommonPageSize)); + for (PhdrEntry *p : part.phdrs) + if (p->p_type == PT_LOAD && (p->p_flags & PF_X)) + fillTrap(Out::bufferStart + alignDown(p->firstSec->offset + p->p_filesz, + config->commonPageSize), + Out::bufferStart + alignTo(p->firstSec->offset + p->p_filesz, + config->commonPageSize)); // Round up the file size of the last segment to the page boundary iff it is // an executable segment to ensure that other tools don't accidentally // trim the instruction padding (e.g. when stripping the file). - PhdrEntry *Last = nullptr; - for (PhdrEntry *P : Part.Phdrs) - if (P->p_type == PT_LOAD) - Last = P; - - if (Last && (Last->p_flags & PF_X)) - Last->p_memsz = Last->p_filesz = - alignTo(Last->p_filesz, Config->CommonPageSize); + PhdrEntry *last = nullptr; + for (PhdrEntry *p : part.phdrs) + if (p->p_type == PT_LOAD) + last = p; + + if (last && (last->p_flags & PF_X)) + last->p_memsz = last->p_filesz = + alignTo(last->p_filesz, config->commonPageSize); } } @@ -2618,26 +2618,26 @@ // In -r or -emit-relocs mode, write the relocation sections first as in // ELf_Rel targets we might find out that we need to modify the relocated // section while doing it. - for (OutputSection *Sec : OutputSections) - if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) - Sec->writeTo(Out::BufferStart + Sec->Offset); - - for (OutputSection *Sec : OutputSections) - if (Sec->Type != SHT_REL && Sec->Type != SHT_RELA) - Sec->writeTo(Out::BufferStart + Sec->Offset); + for (OutputSection *sec : outputSections) + if (sec->type == SHT_REL || sec->type == SHT_RELA) + sec->writeTo(Out::bufferStart + sec->offset); + + for (OutputSection *sec : outputSections) + if (sec->type != SHT_REL && sec->type != SHT_RELA) + sec->writeTo(Out::bufferStart + sec->offset); } // Split one uint8 array into small pieces of uint8 arrays. -static std::vector> split(ArrayRef Arr, - size_t ChunkSize) { - std::vector> Ret; - while (Arr.size() > ChunkSize) { - Ret.push_back(Arr.take_front(ChunkSize)); - Arr = Arr.drop_front(ChunkSize); - } - if (!Arr.empty()) - Ret.push_back(Arr); - return Ret; +static std::vector> split(ArrayRef arr, + size_t chunkSize) { + std::vector> ret; + while (arr.size() > chunkSize) { + ret.push_back(arr.take_front(chunkSize)); + arr = arr.drop_front(chunkSize); + } + if (!arr.empty()) + ret.push_back(arr); + return ret; } // Computes a hash value of Data using a given hash function. @@ -2645,61 +2645,61 @@ // chunks, compute a hash for each chunk, and then compute a hash value // of the hash values. static void -computeHash(llvm::MutableArrayRef HashBuf, - llvm::ArrayRef Data, - std::function Arr)> HashFn) { - std::vector> Chunks = split(Data, 1024 * 1024); - std::vector Hashes(Chunks.size() * HashBuf.size()); +computeHash(llvm::MutableArrayRef hashBuf, + llvm::ArrayRef data, + std::function arr)> hashFn) { + std::vector> chunks = split(data, 1024 * 1024); + std::vector hashes(chunks.size() * hashBuf.size()); // Compute hash values. - parallelForEachN(0, Chunks.size(), [&](size_t I) { - HashFn(Hashes.data() + I * HashBuf.size(), Chunks[I]); + parallelForEachN(0, chunks.size(), [&](size_t i) { + hashFn(hashes.data() + i * hashBuf.size(), chunks[i]); }); // Write to the final output buffer. - HashFn(HashBuf.data(), Hashes); + hashFn(hashBuf.data(), hashes); } template void Writer::writeBuildId() { - if (!Main->BuildId || !Main->BuildId->getParent()) + if (!mainPart->buildId || !mainPart->buildId->getParent()) return; - if (Config->BuildId == BuildIdKind::Hexstring) { - for (Partition &Part : Partitions) - Part.BuildId->writeBuildId(Config->BuildIdVector); + if (config->buildId == BuildIdKind::Hexstring) { + for (Partition &part : partitions) + part.buildId->writeBuildId(config->buildIdVector); return; } // Compute a hash of all sections of the output file. - size_t HashSize = Main->BuildId->HashSize; - std::vector BuildId(HashSize); - llvm::ArrayRef Buf{Out::BufferStart, size_t(FileSize)}; + size_t hashSize = mainPart->buildId->hashSize; + std::vector buildId(hashSize); + llvm::ArrayRef buf{Out::bufferStart, size_t(fileSize)}; - switch (Config->BuildId) { + switch (config->buildId) { case BuildIdKind::Fast: - computeHash(BuildId, Buf, [](uint8_t *Dest, ArrayRef Arr) { - write64le(Dest, xxHash64(Arr)); + computeHash(buildId, buf, [](uint8_t *dest, ArrayRef arr) { + write64le(dest, xxHash64(arr)); }); break; case BuildIdKind::Md5: - computeHash(BuildId, Buf, [&](uint8_t *Dest, ArrayRef Arr) { - memcpy(Dest, MD5::hash(Arr).data(), HashSize); + computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef arr) { + memcpy(dest, MD5::hash(arr).data(), hashSize); }); break; case BuildIdKind::Sha1: - computeHash(BuildId, Buf, [&](uint8_t *Dest, ArrayRef Arr) { - memcpy(Dest, SHA1::hash(Arr).data(), HashSize); + computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef arr) { + memcpy(dest, SHA1::hash(arr).data(), hashSize); }); break; case BuildIdKind::Uuid: - if (auto EC = llvm::getRandomBytes(BuildId.data(), HashSize)) - error("entropy source failure: " + EC.message()); + if (auto ec = llvm::getRandomBytes(buildId.data(), hashSize)) + error("entropy source failure: " + ec.message()); break; default: llvm_unreachable("unknown BuildIdKind"); } - for (Partition &Part : Partitions) - Part.BuildId->writeBuildId(BuildId); + for (Partition &part : partitions) + part.buildId->writeBuildId(buildId); } template void elf::writeResult();