Etienne Pierre-Doray | a88cad0 | 2018-07-25 20:16:02 +0000 | [diff] [blame] | 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 <vector> |
| 12 | |
Samuel Huang | fb34557 | 2018-11-08 21:53:27 +0000 | [diff] [blame] | 13 | #include "base/numerics/safe_conversions.h" |
Etienne Pierre-Doray | a88cad0 | 2018-07-25 20:16:02 +0000 | [diff] [blame] | 14 | #include "components/zucchini/address_translator.h" |
Etienne Pierre-Doray | a88cad0 | 2018-07-25 20:16:02 +0000 | [diff] [blame] | 15 | #include "components/zucchini/buffer_view.h" |
| 16 | #include "components/zucchini/image_utils.h" |
| 17 | #include "components/zucchini/type_elf.h" |
Anton Bikineev | 1a96551 | 2021-05-15 22:35:36 +0000 | [diff] [blame] | 18 | #include "third_party/abseil-cpp/absl/types/optional.h" |
Etienne Pierre-Doray | a88cad0 | 2018-07-25 20:16:02 +0000 | [diff] [blame] | 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> |
| 28 | 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: |
Anton Bikineev | 1a96551 | 2021-05-15 22:35:36 +0000 | [diff] [blame] | 71 | absl::optional<Reference> GetNext() override; |
Etienne Pierre-Doray | a88cad0 | 2018-07-25 20:16:02 +0000 | [diff] [blame] | 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_ |