aboutsummaryrefslogtreecommitdiff
path: root/reloc_utils.h
diff options
context:
space:
mode:
authorSamuel Huang <huangs@chromium.org>2018-03-13 18:19:34 +0000
committerEdward Lesmes <ehmaldonado@google.com>2021-07-23 21:50:59 +0000
commit06f1ae9aaca969ee95ef840f22b6b461c304542d (patch)
treef1e5c6624e70628e81fbf38d6cd14b974abe5d93 /reloc_utils.h
downloadzucchini-06f1ae9aaca969ee95ef840f22b6b461c304542d.tar.gz
[Zucchini] Move Zucchini from /chrome/installer/ to /components/.
(Use "git log --follow" to see older revisions of files). /components/ is the most logical place to put Zucchini, which only depends on /base and /testing/gtest. This move also enables Zucchini to be used by the Component Updater. Details: - Move all files; run the following to change deps and guards: sed 's/chrome\/installer/components/' *.cc *.h -i sed 's/CHROME_INSTALLER/COMPONENTS/' *.cc *.h -i - Sorting works out pretty well! - Change all 'chrome/installer/zucchini' to 'components/zucchini' throughout other parts of the repo; sort if necessary. - Fix 6 'git cl lint' errors. - Change 1 Bind() usage to BindRepeated(). - Update OWNER. Bug: 729154 Change-Id: I50c5a7d411ea85f707b5994ab319dfb2a1acccf7 Reviewed-on: https://chromium-review.googlesource.com/954923 Reviewed-by: Greg Thompson <grt@chromium.org> Reviewed-by: Jochen Eisinger <jochen@chromium.org> Reviewed-by: Samuel Huang <huangs@chromium.org> Commit-Queue: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/master@{#542857} NOKEYCHECK=True GitOrigin-RevId: 577ef6c435e8d43be6e3e60ccbcbd1881780f4ec
Diffstat (limited to 'reloc_utils.h')
-rw-r--r--reloc_utils.h140
1 files changed, 140 insertions, 0 deletions
diff --git a/reloc_utils.h b/reloc_utils.h
new file mode 100644
index 0000000..aac1efb
--- /dev/null
+++ b/reloc_utils.h
@@ -0,0 +1,140 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ZUCCHINI_RELOC_UTILS_H_
+#define COMPONENTS_ZUCCHINI_RELOC_UTILS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/optional.h"
+#include "components/zucchini/address_translator.h"
+#include "components/zucchini/buffer_source.h"
+#include "components/zucchini/buffer_view.h"
+#include "components/zucchini/image_utils.h"
+
+namespace zucchini {
+
+// Win32 PE relocation table stores a list of (type, RVA) pairs. The table is
+// organized into "blocks" for RVAs with common high-order bits (12-31). Each
+// block consists of a list (even length) of 2-byte "units". Each unit stores
+// type (in bits 12-15) and low-order bits (0-11) of an RVA (in bits 0-11). In
+// pseudo-struct:
+// struct Block {
+// uint32_t rva_hi;
+// uint32_t block_size_in_bytes; // 8 + multiple of 4.
+// struct {
+// uint16_t rva_lo:12, type:4; // Little-endian.
+// } units[(block_size_in_bytes - 8) / 2]; // Size must be even.
+// } reloc_table[num_blocks]; // May have padding (type = 0).
+
+// Extracted Win32 reloc Unit data.
+struct RelocUnitWin32 {
+ RelocUnitWin32();
+ RelocUnitWin32(uint8_t type_in, offset_t location_in, rva_t target_rva_in);
+ friend bool operator==(const RelocUnitWin32& a, const RelocUnitWin32& b);
+
+ uint8_t type;
+ offset_t location;
+ rva_t target_rva;
+};
+
+// A reader that parses Win32 PE relocation data and emits RelocUnitWin32 for
+// each reloc unit that lies strictly inside |[lo, hi)|.
+class RelocRvaReaderWin32 {
+ public:
+ enum : ptrdiff_t { kRelocUnitSize = sizeof(uint16_t) };
+
+ // Parses |image| at |reloc_region| to find beginning offsets of each reloc
+ // block. On success, writes the result to |reloc_block_offsets| and returns
+ // true. Otherwise leaves |reloc_block_offsets| in an undetermined state, and
+ // returns false.
+ static bool FindRelocBlocks(ConstBufferView image,
+ BufferRegion reloc_region,
+ std::vector<offset_t>* reloc_block_offsets);
+
+ // |reloc_block_offsets| should be precomputed from FindRelBlocks().
+ RelocRvaReaderWin32(ConstBufferView image,
+ BufferRegion reloc_region,
+ const std::vector<offset_t>& reloc_block_offsets,
+ offset_t lo,
+ offset_t hi);
+ RelocRvaReaderWin32(RelocRvaReaderWin32&&);
+ ~RelocRvaReaderWin32();
+
+ // Successively visits and returns data for each reloc unit, or base::nullopt
+ // when all reloc units are found. Encapsulates block transition details.
+ base::Optional<RelocUnitWin32> GetNext();
+
+ private:
+ // Assuming that |block_begin| points to the beginning of a reloc block, loads
+ // |rva_hi_bits_| and assigns |cur_reloc_units_| as the region containing the
+ // associated units, potentially truncated by |end_it_|. Returns true if reloc
+ // data are available for read, and false otherwise.
+ bool LoadRelocBlock(ConstBufferView::const_iterator block_begin);
+
+ const ConstBufferView image_;
+
+ // End iterator.
+ ConstBufferView::const_iterator end_it_;
+
+ // Unit data of the current reloc block.
+ BufferSource cur_reloc_units_;
+
+ // High-order bits (12-31) for all relocs of the current reloc block.
+ rva_t rva_hi_bits_;
+};
+
+// A reader for Win32 reloc References, implemented as a filtering and
+// translation adaptor of RelocRvaReaderWin32.
+class RelocReaderWin32 : public ReferenceReader {
+ public:
+ // Takes ownership of |reloc_rva_reader|. |offset_bound| specifies the
+ // exclusive upper bound of reloc target offsets, taking account of widths of
+ // targets (which are abs32 References).
+ RelocReaderWin32(RelocRvaReaderWin32&& reloc_rva_reader,
+ uint16_t reloc_type,
+ offset_t offset_bound,
+ const AddressTranslator& translator);
+ ~RelocReaderWin32() override;
+
+ // ReferenceReader:
+ base::Optional<Reference> GetNext() override;
+
+ private:
+ RelocRvaReaderWin32 reloc_rva_reader_;
+ const uint16_t reloc_type_; // uint16_t to simplify shifting (<< 12).
+ const offset_t offset_bound_;
+ AddressTranslator::RvaToOffsetCache entry_rva_to_offset_;
+};
+
+// A writer for Win32 reloc References. This is simpler than the reader since:
+// - No iteration is required.
+// - High-order bits of reloc target RVAs are assumed to be handled elsewhere,
+// so only low-order bits need to be written.
+class RelocWriterWin32 : public ReferenceWriter {
+ public:
+ RelocWriterWin32(uint16_t reloc_type,
+ MutableBufferView image,
+ BufferRegion reloc_region,
+ const std::vector<offset_t>& reloc_block_offsets,
+ const AddressTranslator& translator);
+ ~RelocWriterWin32() override;
+
+ // ReferenceWriter:
+ void PutNext(Reference ref) override;
+
+ private:
+ const uint16_t reloc_type_;
+ MutableBufferView image_;
+ BufferRegion reloc_region_;
+ const std::vector<offset_t>& reloc_block_offsets_;
+ AddressTranslator::OffsetToRvaCache target_offset_to_rva_;
+};
+
+} // namespace zucchini
+
+#endif // COMPONENTS_ZUCCHINI_RELOC_UTILS_H_