1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CRAZY_LINKER_ELF_VIEW_H 6 #define CRAZY_LINKER_ELF_VIEW_H 7 8 #include <string.h> 9 10 #include "crazy_linker_error.h" 11 #include "elf_traits.h" 12 13 namespace crazy { 14 15 class Error; 16 17 // An ElfView holds information describing a given ELF binary file for 18 // the crazy linker. This can be used to describe either system or crazy 19 // libraries. 20 class ElfView { 21 public: ElfView()22 ElfView() { ::memset(this, 0, sizeof(*this)); } 23 ~ElfView()24 ~ElfView() {} 25 26 // Initialize this ElfView from its load address and a copy of its program 27 // header table. 28 // |load_address| is the desired library load address. 29 // |phdr| is a pointer to the library's program header. Note that this can 30 // point to any memory location that contains a valid copy of the header. 31 // I.e. the library does not have to be mapped in the process. 32 // |phdr_count| number of entries in program header table. 33 // On failure, return false and set |error| message. 34 // On success, return true, and sets all fields of the ElfView to the 35 // appropriate values. Note that functions phdr() or dynamic() will always 36 // return an address relative to |load_address|, even if the binary was 37 // not loaded yet in the process. 38 bool InitUnmapped(ELF::Addr load_address, 39 const ELF::Phdr* phdr, 40 size_t phdr_count, 41 Error* error); 42 phdr()43 const ELF::Phdr* phdr() const { return phdr_; } phdr_count()44 size_t phdr_count() const { return phdr_count_; } dynamic()45 const ELF::Dyn* dynamic() const { return dynamic_; } dynamic_count()46 size_t dynamic_count() const { return dynamic_count_; } dynamic_flags()47 size_t dynamic_flags() const { return dynamic_flags_; } load_address()48 size_t load_address() const { return load_address_; } load_size()49 size_t load_size() const { return load_size_; } load_bias()50 size_t load_bias() const { return load_bias_; } 51 52 // Helper class to iterate over the dynamic table. 53 // Usage example: 54 // DynamicIterator iter; 55 // for ( ; iter.HasNext(); iter.SkipNext()) { 56 // if (iter.GetTag() == DT_SOME_TAG) { 57 // ... use iter.GetValue() 58 // ... or iter.GetAddress(load_address) 59 // } 60 // } 61 class DynamicIterator { 62 public: DynamicIterator(const ElfView * view)63 DynamicIterator(const ElfView* view) { 64 dyn_ = view->dynamic(); 65 dyn_limit_ = dyn_ + view->dynamic_count(); 66 } 67 ~DynamicIterator()68 ~DynamicIterator() {} 69 HasNext()70 bool HasNext() const { return dyn_ < dyn_limit_; } GetNext()71 void GetNext() { dyn_ += 1; } 72 GetTag()73 ELF::Addr GetTag() const { return dyn_->d_tag; } 74 GetValue()75 ELF::Addr GetValue() const { return dyn_->d_un.d_val; } 76 GetValuePointer()77 ELF::Addr* GetValuePointer() const { 78 return const_cast<ELF::Addr*>(&dyn_->d_un.d_ptr); 79 } 80 GetOffset()81 uintptr_t GetOffset() const { return dyn_->d_un.d_ptr; } 82 GetAddress(size_t load_bias)83 uintptr_t GetAddress(size_t load_bias) const { 84 return load_bias + dyn_->d_un.d_ptr; 85 } 86 87 private: 88 const ELF::Dyn* dyn_; 89 const ELF::Dyn* dyn_limit_; 90 }; 91 92 // Ensure the RELRO section is read-only after relocations. Assume the 93 // ELF binary is mapped.On failure, return false and set |error| message. 94 bool ProtectRelroSection(Error* error); 95 96 protected: 97 const ELF::Phdr* phdr_; 98 size_t phdr_count_; 99 const ELF::Dyn* dynamic_; 100 size_t dynamic_count_; 101 ELF::Word dynamic_flags_; 102 ELF::Addr load_address_; 103 size_t load_size_; 104 size_t load_bias_; 105 }; 106 107 } // namespace crazy 108 109 #endif // CRAZY_LINKER_ELF_VIEW_H 110