blob: 195b4de6379ac31a97253d152d672e5e2179971e [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_VIEW_H
#define CRAZY_LINKER_ELF_VIEW_H
#include <string.h>
#include "crazy_linker_error.h"
#include "elf_traits.h"
namespace crazy {
class Error;
// An ElfView holds information describing a given ELF binary file for
// the crazy linker. This can be used to describe either system or crazy
// libraries.
class ElfView {
public:
ElfView() = default;
// Initialize this ElfView from its load address and a copy of its program
// header table.
// |load_address| is the desired library load address.
// |phdr| is a pointer to the library's program header. Note that this can
// point to any memory location that contains a valid copy of the header.
// I.e. the library does not have to be mapped in the process.
// |phdr_count| number of entries in program header table.
// On failure, return false and set |error| message.
// On success, return true, and sets all fields of the ElfView to the
// appropriate values. Note that functions phdr() or dynamic() will always
// return an address relative to |load_address|, even if the binary was
// not loaded yet in the process.
bool InitUnmapped(ELF::Addr load_address,
const ELF::Phdr* phdr,
size_t phdr_count,
Error* error);
const ELF::Phdr* phdr() const { return phdr_; }
size_t phdr_count() const { return phdr_count_; }
const ELF::Dyn* dynamic() const { return dynamic_; }
size_t dynamic_count() const { return dynamic_count_; }
size_t dynamic_flags() const { return dynamic_flags_; }
size_t load_address() const { return load_address_; }
size_t load_size() const { return load_size_; }
size_t load_bias() const { return load_bias_; }
// Helper class to iterate over the dynamic table.
// Usage example:
// DynamicIterator iter;
// for ( ; iter.HasNext(); iter.SkipNext()) {
// if (iter.GetTag() == DT_SOME_TAG) {
// ... use iter.GetValue()
// ... or iter.GetAddress(load_address)
// }
// }
class DynamicIterator {
public:
DynamicIterator(const ElfView* view) {
dyn_ = view->dynamic();
dyn_limit_ = dyn_ + view->dynamic_count();
}
~DynamicIterator() {}
bool HasNext() const { return dyn_ < dyn_limit_; }
void GetNext() { dyn_ += 1; }
ELF::Addr GetTag() const { return dyn_->d_tag; }
ELF::Addr GetValue() const { return dyn_->d_un.d_val; }
ELF::Addr* GetValuePointer() const {
return const_cast<ELF::Addr*>(&dyn_->d_un.d_ptr);
}
uintptr_t GetOffset() const { return dyn_->d_un.d_ptr; }
uintptr_t GetAddress(size_t load_bias) const {
return load_bias + dyn_->d_un.d_ptr;
}
private:
const ELF::Dyn* dyn_;
const ELF::Dyn* dyn_limit_;
};
// Ensure the RELRO section is read-only after relocations. Assume the
// ELF binary is mapped.On failure, return false and set |error| message.
bool ProtectRelroSection(Error* error);
#if defined(__arm__) || defined(__aarch64__)
// Register packed relocations to apply.
// |packed_relocs| is a pointer to packed relocations data.
void RegisterPackedRelocations(uint8_t* packed_relocations) {
packed_relocations_ = packed_relocations;
}
uint8_t* packed_relocations() const { return packed_relocations_; }
#endif
protected:
const ELF::Phdr* phdr_ = nullptr;
size_t phdr_count_ = 0;
const ELF::Dyn* dynamic_ = nullptr;
size_t dynamic_count_ = 0;
ELF::Word dynamic_flags_ = 0;
ELF::Addr load_address_ = 0;
size_t load_size_ = 0;
size_t load_bias_ = 0;
#if defined(__arm__) || defined(__aarch64__)
uint8_t* packed_relocations_;
#endif
};
} // namespace crazy
#endif // CRAZY_LINKER_ELF_VIEW_H