reloc_win32.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright 2017 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. #ifndef COMPONENTS_ZUCCHINI_RELOC_WIN32_H_
  5. #define COMPONENTS_ZUCCHINI_RELOC_WIN32_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <vector>
  9. #include "components/zucchini/address_translator.h"
  10. #include "components/zucchini/buffer_source.h"
  11. #include "components/zucchini/buffer_view.h"
  12. #include "components/zucchini/image_utils.h"
  13. #include "third_party/abseil-cpp/absl/types/optional.h"
  14. namespace zucchini {
  15. // Win32 PE relocation table stores a list of (type, RVA) pairs. The table is
  16. // organized into "blocks" for RVAs with common high-order bits (12-31). Each
  17. // block consists of a list (even length) of 2-byte "units". Each unit stores
  18. // type (in bits 12-15) and low-order bits (0-11) of an RVA (in bits 0-11). In
  19. // pseudo-struct:
  20. // struct Block {
  21. // uint32_t rva_hi;
  22. // uint32_t block_size_in_bytes; // 8 + multiple of 4.
  23. // struct {
  24. // uint16_t rva_lo:12, type:4; // Little-endian.
  25. // } units[(block_size_in_bytes - 8) / 2]; // Size must be even.
  26. // } reloc_table[num_blocks]; // May have padding (type = 0).
  27. // Extracted Win32 reloc Unit data.
  28. struct RelocUnitWin32 {
  29. RelocUnitWin32();
  30. RelocUnitWin32(uint8_t type_in, offset_t location_in, rva_t target_rva_in);
  31. friend bool operator==(const RelocUnitWin32& a, const RelocUnitWin32& b);
  32. uint8_t type;
  33. offset_t location;
  34. rva_t target_rva;
  35. };
  36. // A reader that parses Win32 PE relocation data and emits RelocUnitWin32 for
  37. // each reloc unit that lies strictly inside |[lo, hi)|.
  38. class RelocRvaReaderWin32 {
  39. public:
  40. enum : ptrdiff_t { kRelocUnitSize = sizeof(uint16_t) };
  41. // Parses |image| at |reloc_region| to find beginning offsets of each reloc
  42. // block. On success, writes the result to |reloc_block_offsets| and returns
  43. // true. Otherwise leaves |reloc_block_offsets| in an undetermined state, and
  44. // returns false.
  45. static bool FindRelocBlocks(ConstBufferView image,
  46. BufferRegion reloc_region,
  47. std::vector<offset_t>* reloc_block_offsets);
  48. // |reloc_block_offsets| should be precomputed from FindRelBlocks().
  49. RelocRvaReaderWin32(ConstBufferView image,
  50. BufferRegion reloc_region,
  51. const std::vector<offset_t>& reloc_block_offsets,
  52. offset_t lo,
  53. offset_t hi);
  54. RelocRvaReaderWin32(RelocRvaReaderWin32&&);
  55. ~RelocRvaReaderWin32();
  56. // Successively visits and returns data for each reloc unit, or absl::nullopt
  57. // when all reloc units are found. Encapsulates block transition details.
  58. absl::optional<RelocUnitWin32> GetNext();
  59. private:
  60. // Assuming that |block_begin| points to the beginning of a reloc block, loads
  61. // |rva_hi_bits_| and assigns |cur_reloc_units_| as the region containing the
  62. // associated units, potentially truncated by |end_it_|. Returns true if reloc
  63. // data are available for read, and false otherwise.
  64. bool LoadRelocBlock(ConstBufferView::const_iterator block_begin);
  65. const ConstBufferView image_;
  66. // End iterator.
  67. ConstBufferView::const_iterator end_it_;
  68. // Unit data of the current reloc block.
  69. BufferSource cur_reloc_units_;
  70. // High-order bits (12-31) for all relocs of the current reloc block.
  71. rva_t rva_hi_bits_;
  72. };
  73. // A reader for Win32 reloc References, implemented as a filtering and
  74. // translation adaptor of RelocRvaReaderWin32.
  75. class RelocReaderWin32 : public ReferenceReader {
  76. public:
  77. // Takes ownership of |reloc_rva_reader|. |offset_bound| specifies the
  78. // exclusive upper bound of reloc target offsets, taking account of widths of
  79. // targets (which are abs32 References).
  80. RelocReaderWin32(RelocRvaReaderWin32&& reloc_rva_reader,
  81. uint16_t reloc_type,
  82. offset_t offset_bound,
  83. const AddressTranslator& translator);
  84. ~RelocReaderWin32() override;
  85. // ReferenceReader:
  86. absl::optional<Reference> GetNext() override;
  87. private:
  88. RelocRvaReaderWin32 reloc_rva_reader_;
  89. const uint16_t reloc_type_; // uint16_t to simplify shifting (<< 12).
  90. const offset_t offset_bound_;
  91. AddressTranslator::RvaToOffsetCache entry_rva_to_offset_;
  92. };
  93. // A writer for Win32 reloc References. This is simpler than the reader since:
  94. // - No iteration is required.
  95. // - High-order bits of reloc target RVAs are assumed to be handled elsewhere,
  96. // so only low-order bits need to be written.
  97. class RelocWriterWin32 : public ReferenceWriter {
  98. public:
  99. RelocWriterWin32(uint16_t reloc_type,
  100. MutableBufferView image,
  101. BufferRegion reloc_region,
  102. const std::vector<offset_t>& reloc_block_offsets,
  103. const AddressTranslator& translator);
  104. ~RelocWriterWin32() override;
  105. // ReferenceWriter:
  106. void PutNext(Reference ref) override;
  107. private:
  108. const uint16_t reloc_type_;
  109. MutableBufferView image_;
  110. BufferRegion reloc_region_;
  111. const std::vector<offset_t>& reloc_block_offsets_;
  112. AddressTranslator::OffsetToRvaCache target_offset_to_rva_;
  113. };
  114. } // namespace zucchini
  115. #endif // COMPONENTS_ZUCCHINI_RELOC_WIN32_H_