mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[ELF] Support copy relocation on non-default version symbols
Copy relocation on a non-default version symbol is unsupported and can crash at runtime. Fortunately there is a one-line fix which works for most cases: ensure `getSymbolsAt` unconditionally returns `ss`. If two non-default version symbols are defined at the same place and both are copy relocated, our implementation will copy relocated them into different addresses. The pointer inequality is very unlikely an issue. In GNU ld, copy relocating version aliases seems to create more pointer inequality problems than us. ( In glibc, sys_errlist@GLIBC_2.2.5 sys_errlist@GLIBC_2.3 sys_errlist@GLIBC_2.4 are defined at the same place, but it is unlikely they are all copy relocated in one executable. Even if so, the variables are read-only and pointer inequality should not be a problem. ) Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D107535
This commit is contained in:
parent
a46bcc60e5
commit
72d070b4db
@ -527,6 +527,13 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
|
||||
if (auto *alias = dyn_cast_or_null<SharedSymbol>(sym))
|
||||
ret.insert(alias);
|
||||
}
|
||||
|
||||
// The loop does not check SHT_GNU_verneed, so ret does not contain
|
||||
// non-default version symbols. If ss has a non-default version, ret won't
|
||||
// contain ss. Just add ss unconditionally. If a non-default version alias is
|
||||
// separately copy relocated, it and ss will have different addresses.
|
||||
// Fortunately this case is impractical and fails with GNU ld as well.
|
||||
ret.insert(&ss);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,22 @@
|
||||
.data
|
||||
.global foo@v1
|
||||
.type foo@v1, @object
|
||||
.size foo@v1, 4
|
||||
.global foo@@v2
|
||||
.type foo@@v2, @object
|
||||
.size foo@@v2, 8
|
||||
foo@v1:
|
||||
foo@@v2:
|
||||
.global foo_v1
|
||||
.symver foo_v1, foo@v1, remove
|
||||
.type foo_v1, @object
|
||||
.size foo_v1, 4
|
||||
|
||||
.global foo_v2
|
||||
.symver foo_v2, foo@v2, remove
|
||||
.type foo_v2, @object
|
||||
.size foo_v2, 8
|
||||
|
||||
.global foo
|
||||
.symver foo, foo@@@v3
|
||||
.type foo, @object
|
||||
.size foo, 12
|
||||
|
||||
foo_v1:
|
||||
foo_v2:
|
||||
foo:
|
||||
.int 0
|
||||
.int 0
|
||||
.int 0
|
||||
|
@ -1,15 +1,27 @@
|
||||
// REQUIRES: x86
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
|
||||
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-version.s -o %t1.o
|
||||
// RUN: echo "v1 {}; v2 {};" > %t.ver
|
||||
// RUN: ld.lld %t1.o -shared -soname t1.so --version-script=%t.ver -o %t1.so
|
||||
// RUN: ld.lld %t.o %t1.so -o %t
|
||||
// RUN: llvm-readobj --symbols %t | FileCheck %s
|
||||
# REQUIRES: x86
|
||||
## Copy relocate a versioned symbol which has a versioned alias.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %p/Inputs/copy-rel-version.s -o %t.o
|
||||
# RUN: echo 'v1 {}; v2 {}; v3 {};' > %t.ver
|
||||
# RUN: ld.lld %t.o -shared -soname t.so --version-script=%t.ver -o %t.so
|
||||
|
||||
## Copy relocate the default version symbol.
|
||||
# RUN: ld.lld %t1.o %t.so -o %t1
|
||||
# RUN: llvm-readelf --dyn-syms %t1 | FileCheck %s --check-prefix=CHECK1
|
||||
|
||||
# CHECK1: 1: {{.+}} 12 OBJECT GLOBAL DEFAULT [[#]] foo@v3
|
||||
# CHECK1-EMPTY:
|
||||
|
||||
## Copy relocate the non-default version symbol.
|
||||
# RUN: llvm-objcopy --redefine-sym foo=foo@v1 %t1.o %t2.o
|
||||
# RUN: ld.lld %t2.o %t.so -o %t2
|
||||
# RUN: llvm-readelf --dyn-syms %t2 | FileCheck %s --check-prefix=CHECK2
|
||||
|
||||
# CHECK2: 1: [[ADDR:[0-9a-f]+]] 4 OBJECT GLOBAL DEFAULT [[#]] foo@v1
|
||||
# CHECK2-NEXT: 2: [[ADDR]] 12 OBJECT GLOBAL DEFAULT [[#]] foo@v3
|
||||
# CHECK2-EMPTY:
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
leaq foo, %rax
|
||||
|
||||
// CHECK: Name: foo (
|
||||
// CHECK-NEXT: Value:
|
||||
// CHECK-NEXT: Size: 8
|
||||
|
Loading…
Reference in New Issue
Block a user