diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 4676ae8bdbc..bb7c90ac348 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -177,6 +177,19 @@ protected: return DRI; } + bool isExportedToOtherDSO(const Elf_Sym *ESym) const { + unsigned char Binding = ESym->getBinding(); + unsigned char Visibility = ESym->getVisibility(); + + if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_WEAK) + return false; + + if (Visibility != ELF::STV_DEFAULT && Visibility != ELF::STV_PROTECTED) + return false; + + return true; + } + // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. @@ -373,6 +386,9 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; + if (isExportedToOtherDSO(ESym)) + Result |= SymbolRef::SF_Exported; + return Result; } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 9a23c8c4e49..21a49fb6eaa 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -158,7 +158,7 @@ struct Elf_Sym_Base > { Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved + unsigned char st_other; // Visibility in the lower 2 bits, the rest is zero Elf_Half st_shndx; // Which section (header table index) it's defined in }; @@ -167,7 +167,7 @@ struct Elf_Sym_Base > { LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved + unsigned char st_other; // Visibility in the lower 2 bits, the rest is zero Elf_Half st_shndx; // Which section (header table index) it's defined in Elf_Addr st_value; // Value or address associated with the symbol Elf_Xword st_size; // Size of the symbol @@ -176,16 +176,21 @@ struct Elf_Sym_Base > { template struct Elf_Sym_Impl : Elf_Sym_Base { using Elf_Sym_Base::st_info; + using Elf_Sym_Base::st_other; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: unsigned char getBinding() const { return st_info >> 4; } unsigned char getType() const { return st_info & 0x0f; } + unsigned char getVisibility() const { return st_other & 0x3; } void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { st_info = (b << 4) + (t & 0x0f); } + void setVisibility(unsigned char v) { + st_other = (st_other & ~0x3) | (v & 0x3); + } }; /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 435799a34eb..f7b7cb422dd 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -87,9 +87,10 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6, // Specific to the object file format + SF_Exported = 1U << 6, // Symbol is visible to other DSOs + SF_FormatSpecific = 1U << 7, // Specific to the object file format // (e.g. section symbols) - SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary + SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary }; BasicSymbolRef() : OwningObject(nullptr) { } diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index a51a0513529..9b5d18e47da 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -1458,25 +1458,29 @@ struct Elf32_Sym { Elf32_Addr st_value; // Value or address associated with the symbol Elf32_Word st_size; // Size of the symbol unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved + unsigned char st_other; // Visibility in the lower 2 bits, the rest is zero Elf32_Half st_shndx; // Which section (header table index) it's defined in // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: unsigned char getBinding() const { return st_info >> 4; } unsigned char getType() const { return st_info & 0x0f; } + unsigned char getVisibility() const { return st_other & 0x3; } void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { st_info = (b << 4) + (t & 0x0f); } + void setVisibility(unsigned char v) { + st_other = (st_other & ~0x3) | (v & 0x3); + } }; // Symbol table entries for ELF64. struct Elf64_Sym { Elf64_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes - unsigned char st_other; // Must be zero; reserved + unsigned char st_other; // Visibility in the lower 2 bits, the rest is zero Elf64_Half st_shndx; // Which section (header tbl index) it's defined in Elf64_Addr st_value; // Value or address associated with the symbol Elf64_Xword st_size; // Size of the symbol @@ -1485,11 +1489,15 @@ struct Elf64_Sym { // symbol table entries. unsigned char getBinding() const { return st_info >> 4; } unsigned char getType() const { return st_info & 0x0f; } + unsigned char getVisibility() const { return st_other & 0x3; } void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { st_info = (b << 4) + (t & 0x0f); } + void setVisibility(unsigned char v) { + st_other = (st_other & ~0x3) | (v & 0x3); + } }; // The size (in bytes) of symbol table entries. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 488130112de..5c16f0ab712 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -205,10 +205,14 @@ RuntimeDyldImpl::loadObject(std::unique_ptr Obj) { bool IsCode = SI->isText(); unsigned SectionID = findOrEmitSection(*Obj, *SI, IsCode, LocalSections); + // Add the symbol to the local symbol table for this module. LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << " SID: " << SectionID); - GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + // If exported, add to the global symbol table for other modules to also link in. + if (Flags & SymbolRef::SF_Exported) { + GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + } } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 6e83d8182a4..91aa13f7130 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -454,6 +454,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { if (Value && Value != UnknownAddressOrSize) Result |= SymbolRef::SF_Common; } + + if (!(MachOType & MachO::N_PEXT)) + Result |= SymbolRef::SF_Exported; } if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) diff --git a/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s b/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s index 29c95e6ce35..1bf98a93d5d 100644 --- a/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s @@ -18,6 +18,7 @@ _foo: # and therefore ignored. # rtdyld-check: decode_operand(br1, 0)[25:0] = (_foo - br1)[27:2] _test_branch_reloc: + .globl br1 br1: b _foo ret @@ -32,8 +33,10 @@ br1: .globl _test_adrp_ldr .align 2 _test_adrp_ldr: + .globl adrp1 adrp1: adrp x0, _ptr@PAGE + .globl ldr1 ldr1: ldr x0, [x0, _ptr@PAGEOFF] ret @@ -49,8 +52,10 @@ ldr1: .globl _test_adrp_ldr .align 2 _test_got_adrp_ldr: + .globl adrp2 adrp2: adrp x0, _ptr@GOTPAGE + .globl ldr2 ldr2: ldr x0, [x0, _ptr@GOTPAGEOFF] ret diff --git a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s index 7ff3a897576..8214a2594ed 100644 --- a/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s @@ -8,12 +8,15 @@ bar: # Check lower 16-bits of section difference relocation # rtdyld-check: decode_operand(insn1, 1) = (foo$non_lazy_ptr-(nextPC+8))[15:0] + .globl insn1 insn1: movw r0, :lower16:(foo$non_lazy_ptr-(nextPC+8)) # Check upper 16-bits of section difference relocation # rtdyld-check: decode_operand(insn2, 2) = (foo$non_lazy_ptr-(nextPC+8))[31:16] + .globl insn2 insn2: movt r0, :upper16:(foo$non_lazy_ptr-(nextPC+8)) + .globl nextPC nextPC: add r1, r0, r0 @@ -25,6 +28,7 @@ nextPC: # rtdyld-check: *{4}(stub_addr(foo.o, __text, baz) + 4) = baz # # rtdyld-check: decode_operand(insn3, 0) = stub_addr(foo.o, __text, baz) - (insn3 + 8) + .globl insn3 insn3: bl baz @@ -44,6 +48,7 @@ insn4: # rtdyld-check: *{4}foo$non_lazy_ptr = foo .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers .align 2 + .globl foo$non_lazy_ptr foo$non_lazy_ptr: .indirect_symbol foo .long 0 diff --git a/test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s b/test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s index f427b985b58..48b470d9a30 100644 --- a/test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s @@ -6,16 +6,19 @@ .align 4, 0x90 bar: calll tmp0$pb + .globl tmp0$pb tmp0$pb: popl %eax # Test section difference relocation to non-lazy ptr section. # rtdyld-check: decode_operand(inst1, 4) = x$non_lazy_ptr - tmp0$pb + .globl inst1 inst1: movl x$non_lazy_ptr-tmp0$pb(%eax), %eax movl (%eax), %ebx # Test VANILLA relocation to jump table. # rtdyld-check: decode_operand(inst2, 0) = bling$stub - next_pc(inst2) + .globl inst2 inst2: calll bling$stub addl %ebx, %eax @@ -27,11 +30,13 @@ inst3: retl .section __IMPORT,__jump_table,symbol_stubs,pure_instructions+self_modifying_code,5 + .globl bling$stub bling$stub: .indirect_symbol bling .ascii "\364\364\364\364\364" .section __IMPORT,__pointers,non_lazy_symbol_pointers + .globl x$non_lazy_ptr x$non_lazy_ptr: .indirect_symbol x .long 0 diff --git a/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s b/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s index 502f276501f..d9893b0f2bb 100644 --- a/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s +++ b/test/ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s @@ -12,11 +12,13 @@ foo: main: # Test PC-rel branch. # rtdyld-check: decode_operand(insn1, 0) = foo - next_pc(insn1) + .globl insn1 insn1: callq foo # Test PC-rel signed. # rtdyld-check: decode_operand(insn2, 4) = x - next_pc(insn2) + .globl insn2 insn2: movl x(%rip), %eax @@ -25,6 +27,7 @@ insn2: # references the correct GOT entry address: # rtdyld-check: *{8}(stub_addr(test_x86-64.o, __text, y)) = y # rtdyld-check: decode_operand(insn3, 4) = stub_addr(test_x86-64.o, __text, y) - next_pc(insn3) + .globl insn3 insn3: movq y@GOTPCREL(%rip), %rax