Skip to content

Commit

Permalink
elf: skip old version symbols during lookup
Browse files Browse the repository at this point in the history
This patch modifies dynamic loader lookup logic to make it
skip old symbols which are marked as such per version symbols table.

This gap in symbols lookup logic would affect some executables
that depend on libraries that happen to have multiple symbol
implementation versions. The good example is numactl that depends on
libnuma.so.

One can test this patch by trying to run numactl before and after:
```
./scripts/manifest_from_host.sh -w numactl && ./scripts/build fs=rofs -j4 --append-manifest
./scripts/run.py -e '/numactl --show'
```

For details of ELF symbol versioning, please read https://www.akkadia.org/drepper/symbol-versioning.
This paragraph is most applicable to what this patch addresses:

"If the highest bit (no. 15) of the version symbol value is set, the
object is hidden and must not be used.  In this case the linker must
treat the symbol as not present in the object."

Please note this patch does NOT make OSv dynamic linker fully
implement symbols versioning logic.

Signed-off-by: Waldemar Kozaczuk <[email protected]>
Message-Id: <[email protected]>
  • Loading branch information
wkozaczuk authored and nyh committed Aug 29, 2019
1 parent 8cb3ffe commit ed1eed7
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 0 deletions.
6 changes: 6 additions & 0 deletions core/elf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,8 @@ elf64_hash(const char *name)
return h;
}

constexpr Elf64_Versym old_version_symbol_mask = Elf64_Versym(1) << 15;

Elf64_Sym* object::lookup_symbol_old(const char* name)
{
auto symtab = dynamic_ptr<Elf64_Sym>(DT_SYMTAB);
Expand Down Expand Up @@ -842,10 +844,14 @@ Elf64_Sym* object::lookup_symbol_gnu(const char* name)
if (idx == 0) {
return nullptr;
}
auto version_symtab = dynamic_exists(DT_VERSYM) ? dynamic_ptr<Elf64_Versym>(DT_VERSYM) : nullptr;
do {
if ((chains[idx] & ~1) != (hashval & ~1)) {
continue;
}
if (version_symtab && version_symtab[idx] & old_version_symbol_mask) { //Ignore old version symbols
continue;
}
if (strcmp(&strtab[symtab[idx].st_name], name) == 0) {
return &symtab[idx];
}
Expand Down
1 change: 1 addition & 0 deletions include/osv/elf.hh
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ enum {
DT_RUNPATH = 29, // d_val The string table offset of a shared library search path string.
DT_FLAGS = 30, // value is various flags, bits from DF_*.
DT_FLAGS_1 = 0x6ffffffb, // value is various flags, bits from DF_1_*.
DT_VERSYM = 0x6ffffff0, // d_ptr Address of the version symbol table.
DT_LOOS = 0x60000000, // Defines a range of dynamic table tags that are reserved for
// environment-specific use.
DT_HIOS = 0x6FFFFFFF, //
Expand Down

0 comments on commit ed1eed7

Please sign in to comment.