llvm.org GIT mirror llvm / 68b292b
[PowerPC] ELFv2 dynamic loader support This patch enables the new ELFv2 ABI in the runtime dynamic loader. The loader has to implement the following features: - In the ELFv2 ABI, do not look up a function descriptor in .opd, but instead use the local entry point when resolving a direct call. - Update the TOC restore code to use the new TOC slot linkage area offset. - Create PLT stubs appropriate for the ELFv2 ABI. Note that this patch also adds common-code changes. These are necessary because the loader must check the newly added ELF flags: the e_flags header bits encoding the ABI version, and the st_other symbol table entry bits encoding the local entry point offset. There is currently no way to access these, so I've added ObjectFile::getPlatformFlags and SymbolRef::getOther accessors. Reviewed by Hal Finkel. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213491 91177308-0d34-0410-b5e6-96231b3b80d8 Ulrich Weigand 5 years ago
5 changed file(s) with 75 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
6464 uint32_t &Res) const override;
6565 std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
6666 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
67 std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
6768 std::error_code getSymbolType(DataRefImpl Symb,
6869 SymbolRef::Type &Res) const override;
6970 std::error_code getSymbolSection(DataRefImpl Symb,
201202 unsigned getArch() const override;
202203 StringRef getLoadName() const override;
203204
205 std::error_code getPlatformFlags(unsigned &Result) const override {
206 Result = EF.getHeader()->e_flags;
207 return object_error::success;
208 }
209
204210 const ELFFile *getELFFile() const { return &EF; }
205211
206212 bool isDyldType() const { return isDyldELFObject; }
290296 std::error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb,
291297 uint64_t &Result) const {
292298 Result = toELFSymIter(Symb)->st_size;
299 return object_error::success;
300 }
301
302 template
303 std::error_code ELFObjectFile::getSymbolOther(DataRefImpl Symb,
304 uint8_t &Result) const {
305 Result = toELFSymIter(Symb)->st_other;
293306 return object_error::success;
294307 }
295308
148148 std::error_code getAlignment(uint32_t &Result) const;
149149 std::error_code getSize(uint64_t &Result) const;
150150 std::error_code getType(SymbolRef::Type &Result) const;
151 std::error_code getOther(uint8_t &Result) const;
151152
152153 /// @brief Get section this symbol is defined in reference to. Result is
153154 /// end_sections() if it is undefined or is an absolute symbol.
236237 SymbolRef::Type &Res) const = 0;
237238 virtual std::error_code getSymbolSection(DataRefImpl Symb,
238239 section_iterator &Res) const = 0;
240 virtual std::error_code getSymbolOther(DataRefImpl Symb,
241 uint8_t &Res) const {
242 return object_error::invalid_file_type;
243 }
239244
240245 // Same as above for SectionRef.
241246 friend class SectionRef;
327332 /// LC_ID_DYLIB (install name) on MachO.
328333 virtual StringRef getLoadName() const = 0;
329334
335 /// Returns platform-specific object flags, if any.
336 virtual std::error_code getPlatformFlags(unsigned &Result) const {
337 Result = 0;
338 return object_error::invalid_file_type;
339 }
340
330341 /// @returns Pointer to ObjectFile subclass to handle this type of object.
331342 /// @param ObjectPath The path to the object file. ObjectPath.isObject must
332343 /// return true.
382393 return getObject()->getSymbolType(getRawDataRefImpl(), Result);
383394 }
384395
396 inline std::error_code SymbolRef::getOther(uint8_t &Result) const {
397 return getObject()->getSymbolOther(getRawDataRefImpl(), Result);
398 }
399
385400 inline const ObjectFile *SymbolRef::getObject() const {
386401 const SymbolicFile *O = BasicSymbolRef::getObject();
387402 return cast(O);
516516 }
517517 }
518518
519 uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr) {
519 uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
520 unsigned AbiVariant) {
520521 if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be ||
521522 Arch == Triple::arm64 || Arch == Triple::arm64_be) {
522523 // This stub has to be able to access the full address space,
560561 *StubAddr = NopInstr;
561562 return Addr;
562563 } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
563 // PowerPC64 stub: the address points to a function descriptor
564 // instead of the function itself. Load the function address
565 // on r11 and sets it to control register. Also loads the function
566 // TOC in r2 and environment pointer to r11.
564 // Depending on which version of the ELF ABI is in use, we need to
565 // generate one of two variants of the stub. They both start with
566 // the same sequence to load the target address into r12.
567567 writeInt32BE(Addr, 0x3D800000); // lis r12, highest(addr)
568568 writeInt32BE(Addr+4, 0x618C0000); // ori r12, higher(addr)
569569 writeInt32BE(Addr+8, 0x798C07C6); // sldi r12, r12, 32
570570 writeInt32BE(Addr+12, 0x658C0000); // oris r12, r12, h(addr)
571571 writeInt32BE(Addr+16, 0x618C0000); // ori r12, r12, l(addr)
572 writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
573 writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
574 writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
575 writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
576 writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
577 writeInt32BE(Addr+40, 0x4E800420); // bctr
578
572 if (AbiVariant == 2) {
573 // PowerPC64 stub ELFv2 ABI: The address points to the function itself.
574 // The address is already in r12 as required by the ABI. Branch to it.
575 writeInt32BE(Addr+20, 0xF8410018); // std r2, 24(r1)
576 writeInt32BE(Addr+24, 0x7D8903A6); // mtctr r12
577 writeInt32BE(Addr+28, 0x4E800420); // bctr
578 } else {
579 // PowerPC64 stub ELFv1 ABI: The address points to a function descriptor.
580 // Load the function address on r11 and sets it to control register. Also
581 // loads the function TOC in r2 and environment pointer to r11.
582 writeInt32BE(Addr+20, 0xF8410028); // std r2, 40(r1)
583 writeInt32BE(Addr+24, 0xE96C0000); // ld r11, 0(r12)
584 writeInt32BE(Addr+28, 0xE84C0008); // ld r2, 0(r12)
585 writeInt32BE(Addr+32, 0x7D6903A6); // mtctr r11
586 writeInt32BE(Addr+36, 0xE96C0010); // ld r11, 16(r2)
587 writeInt32BE(Addr+40, 0x4E800420); // bctr
588 }
579589 return Addr;
580590 } else if (Arch == Triple::systemz) {
581591 writeInt16BE(Addr, 0xC418); // lgrl %r1,.+8
11401140 }
11411141 } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
11421142 if (RelType == ELF::R_PPC64_REL24) {
1143 // Determine ABI variant in use for this object.
1144 unsigned AbiVariant;
1145 Obj.getObjectFile()->getPlatformFlags(AbiVariant);
1146 AbiVariant &= ELF::EF_PPC64_ABI;
11431147 // A PPC branch relocation will need a stub function if the target is
11441148 // an external symbol (Symbol::ST_Unknown) or if the target address
11451149 // is not within the signed 24-bits branch address.
11471151 uint8_t *Target = Section.Address + Offset;
11481152 bool RangeOverflow = false;
11491153 if (SymType != SymbolRef::ST_Unknown) {
1150 // A function call may points to the .opd entry, so the final symbol
1151 // value
1152 // in calculated based in the relocation values in .opd section.
1153 findOPDEntrySection(Obj, ObjSectionToID, Value);
1154 if (AbiVariant != 2) {
1155 // In the ELFv1 ABI, a function call may point to the .opd entry,
1156 // so the final symbol value is calculated based on the relocation
1157 // values in the .opd section.
1158 findOPDEntrySection(Obj, ObjSectionToID, Value);
1159 } else {
1160 // In the ELFv2 ABI, a function symbol may provide a local entry
1161 // point, which must be used for direct calls.
1162 uint8_t SymOther;
1163 Symbol->getOther(SymOther);
1164 Value.Addend += ELF::decodePPC64LocalEntryOffset(SymOther);
1165 }
11541166 uint8_t *RelocTarget = Sections[Value.SectionID].Address + Value.Addend;
11551167 int32_t delta = static_cast(Target - RelocTarget);
11561168 // If it is within 24-bits branch range, just set the branch target
11781190 DEBUG(dbgs() << " Create a new stub function\n");
11791191 Stubs[Value] = Section.StubOffset;
11801192 uint8_t *StubTargetAddr =
1181 createStubFunction(Section.Address + Section.StubOffset);
1193 createStubFunction(Section.Address + Section.StubOffset,
1194 AbiVariant);
11821195 RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
11831196 ELF::R_PPC64_ADDR64, Value.Addend);
11841197
12161229 RelType, 0);
12171230 Section.StubOffset += getMaxStubSize();
12181231 }
1219 if (SymType == SymbolRef::ST_Unknown)
1232 if (SymType == SymbolRef::ST_Unknown) {
12201233 // Restore the TOC for external calls
1221 writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1)
1234 if (AbiVariant == 2)
1235 writeInt32BE(Target + 4, 0xE8410018); // ld r2,28(r1)
1236 else
1237 writeInt32BE(Target + 4, 0xE8410028); // ld r2,40(r1)
1238 }
12221239 }
12231240 } else if (RelType == ELF::R_PPC64_TOC16 ||
12241241 RelType == ELF::R_PPC64_TOC16_DS ||
311311
312312 /// \brief Emits long jump instruction to Addr.
313313 /// \return Pointer to the memory area for emitting target address.
314 uint8_t *createStubFunction(uint8_t *Addr);
314 uint8_t *createStubFunction(uint8_t *Addr, unsigned AbiVariant = 0);
315315
316316 /// \brief Resolves relocations from Relocs list with address from Value.
317317 void resolveRelocationList(const RelocationList &Relocs, uint64_t Value);