blob: 6bd13a7b8a88fba24019af211e34c0965b1037e2 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRAZY_LINKER_ELF_SYMBOLS_H
#define CRAZY_LINKER_ELF_SYMBOLS_H
#include "crazy_linker_elf_hash_table.h"
#include "crazy_linker_gnu_hash_table.h"
#include "elf_traits.h"
#include <string.h>
namespace crazy {
class ElfView;
// An ElfSymbols instance holds information about symbols in a mapped ELF
// binary.
class ElfSymbols {
public:
ElfSymbols() = default;
// Constructor used for unit-testing.
ElfSymbols(const ELF::Sym* symbol_table,
const char* string_table,
uintptr_t dt_elf_hash,
uintptr_t dt_gnu_hash);
// Returns true iff instance is valid.
bool IsValid() const;
// Initializes instance from |view|. Returns true on success, or false if
// the ELF image is malformed.
bool Init(const ElfView* view);
// Returns the symbol table entry associated with |symbol_name|, or nullptr.
const ELF::Sym* LookupByName(const char* symbol_name) const;
// Returns the symbol table entry associated with |symbol_id|.
const ELF::Sym* LookupById(size_t symbol_id) const {
return &symbol_table_[symbol_id];
}
// Returns the symbol table entry corresponding to a given |address|.
// |load_bias| must be the ELF image's load bias. Return nullptr if not found.
const ELF::Sym* LookupByAddress(void* address, size_t load_bias) const;
// Returns true iff symbol with id |symbol_id| is weak.
bool IsWeakById(size_t symbol_id) const {
return ELF_ST_BIND(symbol_table_[symbol_id].st_info) == STB_WEAK;
}
// Returns the name of the symbol associated with |symbol_id|.
const char* LookupNameById(size_t symbol_id) const {
const ELF::Sym* sym = LookupById(symbol_id);
if (!sym)
return nullptr;
return string_table_ + sym->st_name;
}
// Returns the address of the symbol identified by |symbol_name|. |load_bias|
// must be the ELF image's load bias. Return nullptr if not found.
void* LookupAddressByName(const char* symbol_name, size_t load_bias) const {
const ELF::Sym* sym = LookupByName(symbol_name);
if (!sym)
return nullptr;
return reinterpret_cast<void*>(load_bias + sym->st_value);
}
// Lookups symbol information that is nearest to |address|, where |load_bias|
// is the ELF image load bias. On success, return true and set |*sym_name|,
// |*sym_addre| and |*sym_size|. On failure, return false.
bool LookupNearestByAddress(void* address,
size_t load_bias,
const char** sym_name,
void** sym_addr,
size_t* sym_size) const;
// Returns string identified by |str_id|.
const char* GetStringById(size_t str_id) const {
return string_table_ + str_id;
}
const char* string_table() const { return string_table_; }
private:
// Simple range view for the dynamic symbols within |symbol_table_|.
// Provides begin() and end() to allow for-range loops.
class DynSymbols {
public:
DynSymbols(const ELF::Sym* symbols, size_t start, size_t count)
: begin_(symbols + start), end_(symbols + start + count) {}
const ELF::Sym* begin() const { return begin_; }
const ELF::Sym* end() const { return end_; }
private:
const ELF::Sym* begin_;
const ELF::Sym* end_;
};
DynSymbols GetDynSymbols() const;
const ELF::Sym* symbol_table_ = nullptr;
const char* string_table_ = nullptr;
ElfHashTable elf_hash_ = {};
GnuHashTable gnu_hash_ = {};
};
} // namespace crazy
#endif // CRAZY_LINKER_ELF_SYMBOLS_H