assert(r.kindArch() == Reference::KindArch::ARM);
switch (r.kindValue()) {
case llvm::ELF::R_ARM_TLS_TPOFF32:
+ case llvm::ELF::R_ARM_COPY:
return true;
default:
return false;
}
}
+ bool isCopyRelocation(const Reference &r) const override {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::ARM);
+ return r.kindValue() == llvm::ELF::R_ARM_COPY;
+ }
+
bool isPLTRelocation(const Reference &r) const override {
if (r.kindNamespace() != Reference::KindNamespace::ELF)
return false;
Alignment alignment() const override { return 4; }
};
+/// \brief Atom which represents an object for which a COPY relocation will
+/// be generated.
+class ARMObjectAtom : public ObjectAtom {
+public:
+ ARMObjectAtom(const File &f) : ObjectAtom(f) {}
+ Alignment alignment() const override { return 4; }
+};
+
class ELFPassFile : public SimpleFile {
public:
ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
got->setOrdinal(ordinal++);
mf->addAtom(*got);
}
+ for (auto &objectKV : _objectAtoms) {
+ auto &obj = objectKV.second;
+ obj->setOrdinal(ordinal++);
+ mf->addAtom(*obj);
+ }
for (auto &veneerKV : _veneerAtoms) {
auto &veneer = veneerKV.second;
auto *m = veneer._mapping;
/// \brief Map Atoms to their GOT entries.
llvm::MapVector<const Atom *, GOTAtom *> _gotAtoms;
+ /// \brief Map Atoms to their Object entries.
+ llvm::MapVector<const Atom *, ObjectAtom *> _objectAtoms;
+
/// \brief Map Atoms to their PLT entries depending on the code model.
struct PLTWithVeneer {
PLTWithVeneer(PLTAtom *p = nullptr, PLTAtom *v = nullptr)
return g;
}
+ const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
+ if (auto obj = _objectAtoms.lookup(a))
+ return obj;
+
+ auto oa = new (_file._alloc) ARMObjectAtom(_file);
+ oa->addReferenceELF_ARM(R_ARM_COPY, 0, oa, 0);
+
+ oa->_name = a->name();
+ oa->_size = a->size();
+
+ _objectAtoms[a] = oa;
+ return oa;
+ }
+
/// \brief Handle ordinary relocation references.
std::error_code handlePlain(bool fromThumb, const Reference &ref) {
if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
- if (sla->type() == SharedLibraryAtom::Type::Data) {
- llvm_unreachable("Handle object entries");
+ if (sla->type() == SharedLibraryAtom::Type::Data &&
+ _ctx.getOutputELFType() == llvm::ELF::ET_EXEC) {
+ const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
} else if (sla->type() == SharedLibraryAtom::Type::Code) {
const_cast<Reference &>(ref).setTarget(getPLTEntry(sla, fromThumb));
}
--- /dev/null
+# Check handling of R_ARM_COPY relocation.
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi \
+# RUN: --noinhibit-exec %t-o.o -lobj -L%p/Inputs -o %t
+# RUN: llvm-objdump -s -t %t | FileCheck %s
+# RUN: llvm-readobj -relocations %t | FileCheck -check-prefix=READOBJ %s
+
+# CHECK: Contents of section .rel.dyn:
+# CHECK-NEXT: 400138 00104000 14010000
+# addr = 0x401000 ^^ ^^ rel_type = 0x14 => R_ARM_COPY
+# CHECK: SYMBOL TABLE:
+# CHECK: 00401000 g .bss 00000004 object
+#
+# READOBJ: 0x401000 R_ARM_COPY object
+
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_ARM
+ Flags: [ EF_ARM_EABI_VER5 ]
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: 80B483B000AF40F20003C0F200031B687B60002318460C37BD465DF8047B7047
+ - Name: .rel.text
+ Type: SHT_REL
+ Link: .symtab
+ AddressAlign: 0x0000000000000004
+ Info: .text
+ Relocations:
+ - Offset: 0x0000000000000006
+ Symbol: object
+ Type: R_ARM_THM_MOVW_ABS_NC
+ - Offset: 0x000000000000000A
+ Symbol: object
+ Type: R_ARM_THM_MOVT_ABS
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+Symbols:
+ Local:
+ - Name: '$t'
+ Section: .text
+ Global:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x0000000000000001
+ - Name: object
+...