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