mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 06:05:44 +00:00
464da0f9c2
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.
56 lines
1.7 KiB
C++
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;
|
|
}
|