blob: ebf2577bbd007060cd857f03cb06a2cb3cffc238 [file] [log] [blame]
Etienne Pierre-Doraya88cad02018-07-25 20:16:02 +00001// 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 Huangfb345572018-11-08 21:53:27 +000013#include "base/numerics/safe_conversions.h"
Etienne Pierre-Doraya88cad02018-07-25 20:16:02 +000014#include "components/zucchini/address_translator.h"
Etienne Pierre-Doraya88cad02018-07-25 20:16:02 +000015#include "components/zucchini/buffer_view.h"
16#include "components/zucchini/image_utils.h"
17#include "components/zucchini/type_elf.h"
Anton Bikineev1a965512021-05-15 22:35:36 +000018#include "third_party/abseil-cpp/absl/types/optional.h"
Etienne Pierre-Doraya88cad02018-07-25 20:16:02 +000019
20namespace 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.
24struct 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_|.
52class 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 Bikineev1a965512021-05-15 22:35:36 +000071 absl::optional<Reference> GetNext() override;
Etienne Pierre-Doraya88cad02018-07-25 20:16:02 +000072
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
84class 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_