blob: a2d42c0f824479045b42c3a437a72deb6c2e43eb [file] [log] [blame]
// Copyright (c) 2013 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_RELOCATOR_H
#define CRAZY_LINKER_ELF_RELOCATOR_H
#include "crazy_linker_error.h"
#include "elf_traits.h"
namespace crazy {
// A class used to perform ELF relocations in a library.
// Usage is:
// 1/ Create new instance.
// 2/ Call Init().
// 3/ Call Apply() to apply all relocations.
//
// If any of these steps fail, the library will be in inconsistent
// state and must be unloaded/unmapped as soon as possible by the
// caller to avoid any issue.
class ElfRelocator {
public:
// Abstract class used to resolve symbol names into addresses.
// Callers of ::Apply() should pass the address of a derived class
// that properly implements the Lookup() method.
class SymbolResolver {
public:
SymbolResolver() {}
~SymbolResolver() {}
virtual void* Lookup(const char* symbol_name) = 0;
};
ElfRelocator();
// Initialize the relocator. This will parse the library's dynamic
// table to populate the structure.
// |phdr| is the library's program header address.
// |phdr_count| is the number of program header entries.
// |load_bias| is the library load bias.
// |dynamic| is the library's dynamic table.
// |dyn_count| is the number of dynamic table entries.
// On failure, return false and sets the |error| message.
bool Init(const ELF::Phdr* phdr,
size_t phdr_count,
size_t load_bias,
const ELF::Dyn* dynamic,
size_t dyn_count,
Error* error);
// After initialization, apply all relocations in the library.
// |resolver| must be an non-abstract instance of SymbolResolver
// that will be used to resolve symbol lookups during relocations.
// |string_table| is the library's string table.
// |symbol_table| is the library's symbol table.
// On failure, returns false and sets the |error| message.
bool Apply(SymbolResolver* resolver,
const char* string_table,
const ELF::Sym* symbol_table,
Error* error);
private:
bool ApplyRelocs(const ELF::Rel* rel, size_t rel_count, Error* error);
#ifdef __mips__
bool RelocateMipsGot(Error* error);
#endif
// Program header table
const ELF::Phdr* phdr_;
size_t phdr_count_;
// Load bias to apply to all virtual address in the library.
size_t load_bias_;
// Relocations for the GOT and the PLT section that contains
// the trampolines to call external symbols.
ELF::Addr* plt_got_;
ELF::Rel* plt_rel_;
size_t plt_rel_count_;
// Relocations for the rest of the library.
ELF::Rel* rel_;
size_t rel_count_;
#if defined(__mips__)
// MIPS-specific relocation fields.
ELF::Word mips_symtab_count_;
ELF::Word mips_local_got_count_;
ELF::Word mips_gotsym_;
#endif
bool has_text_relocations_;
bool has_symbolic_;
// Used only during Apply().
SymbolResolver* resolver_;
const char* string_table_;
const ELF::Sym* symbol_table_;
};
} // namespace crazy
#endif // CRAZY_LINKER_ELF_RELOCATOR_H