forked from OSchip/llvm-project
[ELF] - Implemented version script hierarchies.
Patch implements hierarchies for version scripts. This allows to handle script files with dependencies, like next one has: LIBSAMPLE_1.0{ global: a; }; LIBSAMPLE_2.0 { global: b; }LIBSAMPLE_1.0; Differential revision: http://reviews.llvm.org/D21556 llvm-svn: 273423
This commit is contained in:
parent
dce8e4173b
commit
0ab48b7334
|
@ -37,6 +37,7 @@ enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
|
|||
struct Version {
|
||||
Version(llvm::StringRef Name) : Name(Name) {}
|
||||
llvm::StringRef Name;
|
||||
llvm::StringRef Parent;
|
||||
std::vector<llvm::StringRef> Globals;
|
||||
size_t NameOff; // Offset in string table.
|
||||
};
|
||||
|
|
|
@ -1462,6 +1462,10 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
|
|||
|
||||
this->Header.sh_size =
|
||||
(sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum();
|
||||
for (Version &V : Config->SymbolVersions)
|
||||
if (!V.Parent.empty())
|
||||
this->Header.sh_size += sizeof(Elf_Verdaux);
|
||||
|
||||
this->Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
|
||||
this->Header.sh_addralign = sizeof(uint32_t);
|
||||
|
||||
|
@ -1471,12 +1475,22 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalize() {
|
|||
this->Header.sh_info = getVerDefNum();
|
||||
}
|
||||
|
||||
static size_t getVersionNameStrTabOffset(StringRef Name) {
|
||||
for (Version &V : Config->SymbolVersions)
|
||||
if (V.Name == Name)
|
||||
return V.NameOff;
|
||||
error("unknown version name " + Name + " used as a dependency");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class Elf_Verdef, class Elf_Verdaux>
|
||||
static void writeDefinition(Elf_Verdef *&Verdef, Elf_Verdaux *&Verdaux,
|
||||
uint32_t Flags, uint32_t Index, StringRef Name,
|
||||
size_t StrTabOffset) {
|
||||
size_t StrTabOffset, StringRef ParentName) {
|
||||
bool HasParent = !ParentName.empty();
|
||||
|
||||
Verdef->vd_version = 1;
|
||||
Verdef->vd_cnt = 1;
|
||||
Verdef->vd_cnt = HasParent ? 2 : 1;
|
||||
Verdef->vd_aux =
|
||||
reinterpret_cast<char *>(Verdaux) - reinterpret_cast<char *>(Verdef);
|
||||
Verdef->vd_next = sizeof(Elf_Verdef);
|
||||
|
@ -1487,6 +1501,12 @@ static void writeDefinition(Elf_Verdef *&Verdef, Elf_Verdaux *&Verdaux,
|
|||
++Verdef;
|
||||
|
||||
Verdaux->vda_name = StrTabOffset;
|
||||
if (HasParent) {
|
||||
Verdaux->vda_next = sizeof(Elf_Verdaux);
|
||||
++Verdaux;
|
||||
Verdaux->vda_name = getVersionNameStrTabOffset(ParentName);
|
||||
}
|
||||
|
||||
Verdaux->vda_next = 0;
|
||||
++Verdaux;
|
||||
}
|
||||
|
@ -1498,11 +1518,12 @@ void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
reinterpret_cast<Elf_Verdaux *>(Verdef + getVerDefNum());
|
||||
|
||||
writeDefinition(Verdef, Verdaux, VER_FLG_BASE, 1, getFileDefName(),
|
||||
FileDefNameOff);
|
||||
FileDefNameOff, "" /* Parent */);
|
||||
|
||||
uint32_t I = 2;
|
||||
for (Version &V : Config->SymbolVersions)
|
||||
writeDefinition(Verdef, Verdaux, 0 /* Flags */, I++, V.Name, V.NameOff);
|
||||
writeDefinition(Verdef, Verdaux, 0 /* Flags */, I++, V.Name, V.NameOff,
|
||||
V.Parent);
|
||||
|
||||
Verdef[-1].vd_next = 0;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ void VersionScriptParser::parseVersion(StringRef Version) {
|
|||
parseVersionSymbols(Version);
|
||||
|
||||
expect("}");
|
||||
if (!Version.empty() && peek() != ";")
|
||||
Config->SymbolVersions.back().Parent = next();
|
||||
expect(";");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
# REQUIRES: x86
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
# RUN: echo "LIBSAMPLE_1.0{ \
|
||||
# RUN: global: a; \
|
||||
# RUN: local: *; }; \
|
||||
# RUN: LIBSAMPLE_2.0{ \
|
||||
# RUN: global: b; \
|
||||
# RUN: local: *; }LIBSAMPLE_1.0; \
|
||||
# RUN: LIBSAMPLE_3.0{ \
|
||||
# RUN: global: c; \
|
||||
# RUN: local: *; }LIBSAMPLE_2.0;" > %t.script
|
||||
# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so
|
||||
# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s
|
||||
|
||||
# DSO: SHT_GNU_verdef {
|
||||
# DSO-NEXT: Definition {
|
||||
# DSO-NEXT: Version: 1
|
||||
# DSO-NEXT: Flags: Base
|
||||
# DSO-NEXT: Index: 1
|
||||
# DSO-NEXT: Hash: 127830196
|
||||
# DSO-NEXT: Name: shared
|
||||
# DSO-NEXT: }
|
||||
# DSO-NEXT: Definition {
|
||||
# DSO-NEXT: Version: 1
|
||||
# DSO-NEXT: Flags: 0x0
|
||||
# DSO-NEXT: Index: 2
|
||||
# DSO-NEXT: Hash: 98457184
|
||||
# DSO-NEXT: Name: LIBSAMPLE_1.0
|
||||
# DSO-NEXT: }
|
||||
# DSO-NEXT: Definition {
|
||||
# DSO-NEXT: Version: 1
|
||||
# DSO-NEXT: Flags: 0x0
|
||||
# DSO-NEXT: Index: 3
|
||||
# DSO-NEXT: Hash: 98456416
|
||||
# DSO-NEXT: Name: LIBSAMPLE_2.0
|
||||
# DSO-NEXT: Predecessor: LIBSAMPLE_1.0
|
||||
# DSO-NEXT: }
|
||||
# DSO-NEXT: Definition {
|
||||
# DSO-NEXT: Version: 1
|
||||
# DSO-NEXT: Flags: 0x0
|
||||
# DSO-NEXT: Index: 4
|
||||
# DSO-NEXT: Hash: 98456672
|
||||
# DSO-NEXT: Name: LIBSAMPLE_3.0
|
||||
# DSO-NEXT: Predecessor: LIBSAMPLE_2.0
|
||||
# DSO-NEXT: }
|
||||
# DSO-NEXT: }
|
||||
|
||||
# RUN: echo "LIBSAMPLE_1.0{ \
|
||||
# RUN: global: a; \
|
||||
# RUN: local: *; }; \
|
||||
# RUN: LIBSAMPLE_2.0{ \
|
||||
# RUN: global: b; \
|
||||
# RUN: local: *; }LIBSAMPLE_X.X; " > %t.script
|
||||
# RUN: not ld.lld --version-script %t.script -shared %t.o -o %t.so 2>&1 \
|
||||
# RUN: | FileCheck -check-prefix=ERR %s
|
||||
# ERR: unknown version name LIBSAMPLE_X.X used as a dependency
|
Loading…
Reference in New Issue