1 // Copyright 2018 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 COMPONENTS_ZUCCHINI_RELOC_ELF_H_ 6 #define COMPONENTS_ZUCCHINI_RELOC_ELF_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <optional> 12 #include <vector> 13 14 #include "base/numerics/safe_conversions.h" 15 #include "components/zucchini/address_translator.h" 16 #include "components/zucchini/buffer_view.h" 17 #include "components/zucchini/image_utils.h" 18 #include "components/zucchini/type_elf.h" 19 20 namespace zucchini { 21 22 // Section dimensions for ELF files, to store relevant dimensions data from 23 // Elf32_Shdr and Elf64_Shdr, while reducing code duplication from templates. 24 struct SectionDimensionsElf { 25 SectionDimensionsElf() = default; 26 27 template <class Elf_Shdr> SectionDimensionsElfSectionDimensionsElf28 explicit SectionDimensionsElf(const Elf_Shdr& section) 29 : region(BufferRegion{base::checked_cast<size_t>(section.sh_offset), 30 base::checked_cast<size_t>(section.sh_size)}), 31 entry_size(base::checked_cast<offset_t>(section.sh_entsize)) {} 32 33 friend bool operator<(const SectionDimensionsElf& a, 34 const SectionDimensionsElf& b) { 35 return a.region.offset < b.region.offset; 36 } 37 38 friend bool operator<(offset_t offset, const SectionDimensionsElf& section) { 39 return offset < section.region.offset; 40 } 41 42 BufferRegion region; 43 offset_t entry_size; // Varies across REL / RELA sections. 44 }; 45 46 // A Generator to visit all reloc structs located in [|lo|, |hi|) (excluding 47 // truncated strct at |lo| but inlcuding truncated struct at |hi|), and emit 48 // valid References with |rel_type|. This implements a nested loop unrolled into 49 // a generator: the outer loop has |cur_section_dimensions_| visiting 50 // |reloc_section_dims| (sorted by |region.offset|), and the inner loop has 51 // |cursor_| visiting successive reloc structs within |cur_section_dimensions_|. 52 class RelocReaderElf : public ReferenceReader { 53 public: 54 RelocReaderElf( 55 ConstBufferView image, 56 Bitness bitness, 57 const std::vector<SectionDimensionsElf>& reloc_section_dimensions, 58 uint32_t rel_type, 59 offset_t lo, 60 offset_t hi, 61 const AddressTranslator& translator); 62 ~RelocReaderElf() override; 63 64 // If |rel| contains |r_offset| for |rel_type_|, return the RVA. Otherwise 65 // return |kInvalidRva|. These also handle Elf*_Rela, by using the fact that 66 // Elf*_Rel is a prefix of Elf*_Rela. 67 rva_t GetRelocationTarget(elf::Elf32_Rel rel) const; 68 rva_t GetRelocationTarget(elf::Elf64_Rel rel) const; 69 70 // ReferenceReader: 71 std::optional<Reference> GetNext() override; 72 73 private: 74 const ConstBufferView image_; 75 const Bitness bitness_; 76 const uint32_t rel_type_; 77 const std::vector<SectionDimensionsElf>& reloc_section_dimensions_; 78 std::vector<SectionDimensionsElf>::const_iterator cur_section_dimensions_; 79 offset_t hi_; 80 offset_t cursor_; 81 AddressTranslator::RvaToOffsetCache target_rva_to_offset_; 82 }; 83 84 class RelocWriterElf : public ReferenceWriter { 85 public: 86 RelocWriterElf(MutableBufferView image, 87 Bitness bitness, 88 const AddressTranslator& translator); 89 ~RelocWriterElf() override; 90 91 // ReferenceWriter: 92 void PutNext(Reference ref) override; 93 94 private: 95 MutableBufferView image_; 96 const Bitness bitness_; 97 AddressTranslator::OffsetToRvaCache target_offset_to_rva_; 98 }; 99 100 } // namespace zucchini 101 102 #endif // COMPONENTS_ZUCCHINI_RELOC_ELF_H_ 103