gecko-dev/mozglue/linker/BaseElf.cpp
Mike Hommey 464da0f9c2 Bug 1077384 - Make libmozglue a pseudo-LD_PRELOAD on android. r=nfroyd
In order to avoid adding more dlsym overhead than there already is, resolve
symbols directly in the library containing the linker. (GetSymbolPtr is
essentially free ; dlsym makes the system linker compule a ElfHash itself,
and that's quite expensive to do on all symbols)

This also paves the way for direct symbol resolution in all system libraries.
2014-10-07 07:42:18 +09:00

56 lines
1.7 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BaseElf.h"
#include "Elfxx.h"
#include "Logging.h"
using namespace Elf;
unsigned long
BaseElf::Hash(const char *symbol)
{
const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
unsigned long h = 0, g;
while (*sym) {
h = (h << 4) + *sym++;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
}
void *
BaseElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
{
const Sym *sym = GetSymbol(symbol, hash);
void *ptr = nullptr;
if (sym && sym->st_shndx != SHN_UNDEF)
ptr = GetPtr(sym->st_value);
DEBUG_LOG("BaseElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
return ptr;
}
const Sym *
BaseElf::GetSymbol(const char *symbol, unsigned long hash) const
{
/* Search symbol with the buckets and chains tables.
* The hash computed from the symbol name gives an index in the buckets
* table. The corresponding value in the bucket table is an index in the
* symbols table and in the chains table.
* If the corresponding symbol in the symbols table matches, we're done.
* Otherwise, the corresponding value in the chains table is a new index
* in both tables, which corresponding symbol is tested and so on and so
* forth */
size_t bucket = hash % buckets.numElements();
for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
continue;
return &symtab[y];
}
return nullptr;
}