mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[MCJIT] Make MCJIT honor symbol visibility settings when populating the global
symbol table. Patch by Anthony Pesch. Thanks Anthony! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220245 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a37862e2de
commit
32aaaeaa05
@ -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<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
|
||||
EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON)
|
||||
Result |= SymbolRef::SF_Common;
|
||||
|
||||
if (isExportedToOtherDSO(ESym))
|
||||
Result |= SymbolRef::SF_Exported;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > {
|
||||
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<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
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<ELFType<TargetEndianness, MaxAlign, true> > {
|
||||
template <class ELFT>
|
||||
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
|
||||
using Elf_Sym_Base<ELFT>::st_info;
|
||||
using Elf_Sym_Base<ELFT>::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
|
||||
|
@ -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) { }
|
||||
|
@ -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.
|
||||
|
@ -205,10 +205,14 @@ RuntimeDyldImpl::loadObject(std::unique_ptr<ObjectImage> 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");
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user