abs32_utils.cc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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. #include "components/zucchini/abs32_utils.h"
  5. #include <algorithm>
  6. #include <type_traits>
  7. #include <utility>
  8. #include "base/check_op.h"
  9. #include "components/zucchini/io_utils.h"
  10. namespace zucchini {
  11. namespace {
  12. // Templated helper for AbsoluteAddress::Read().
  13. template <typename T>
  14. bool ReadAbs(ConstBufferView image, offset_t offset, uint64_t* value) {
  15. static_assert(std::is_unsigned<T>::value, "Value type must be unsigned.");
  16. if (!image.can_access<T>(offset))
  17. return false;
  18. *value = static_cast<uint64_t>(image.read<T>(offset));
  19. return true;
  20. }
  21. // Templated helper for AbsoluteAddress::Write().
  22. template <typename T>
  23. bool WriteAbs(offset_t offset, T value, MutableBufferView* image) {
  24. static_assert(std::is_unsigned<T>::value, "Value type must be unsigned.");
  25. if (!image->can_access<T>(offset))
  26. return false;
  27. image->write<T>(offset, value);
  28. return true;
  29. }
  30. } // namespace
  31. /******** AbsoluteAddress ********/
  32. AbsoluteAddress::AbsoluteAddress(Bitness bitness, uint64_t image_base)
  33. : bitness_(bitness), image_base_(image_base), value_(image_base) {
  34. CHECK(bitness_ == kBit64 || image_base_ < 0x100000000ULL);
  35. }
  36. AbsoluteAddress::AbsoluteAddress(AbsoluteAddress&&) = default;
  37. AbsoluteAddress::~AbsoluteAddress() = default;
  38. bool AbsoluteAddress::FromRva(rva_t rva) {
  39. if (rva >= kRvaBound)
  40. return false;
  41. uint64_t value = image_base_ + rva;
  42. // Check overflow, which manifests as |value| "wrapping around", resulting in
  43. // |value| less than |image_base_| (preprocessing needed for 32-bit).
  44. if (((bitness_ == kBit32) ? (value & 0xFFFFFFFFU) : value) < image_base_)
  45. return false;
  46. value_ = value;
  47. return true;
  48. }
  49. rva_t AbsoluteAddress::ToRva() const {
  50. if (value_ < image_base_)
  51. return kInvalidRva;
  52. uint64_t raw_rva = value_ - image_base_;
  53. if (raw_rva >= kRvaBound)
  54. return kInvalidRva;
  55. return static_cast<rva_t>(raw_rva);
  56. }
  57. bool AbsoluteAddress::Read(offset_t offset, const ConstBufferView& image) {
  58. // Read raw data; |value_| is not guaranteed to represent a valid RVA.
  59. if (bitness_ == kBit32)
  60. return ReadAbs<uint32_t>(image, offset, &value_);
  61. DCHECK_EQ(kBit64, bitness_);
  62. return ReadAbs<uint64_t>(image, offset, &value_);
  63. }
  64. bool AbsoluteAddress::Write(offset_t offset, MutableBufferView* image) {
  65. if (bitness_ == kBit32)
  66. return WriteAbs<uint32_t>(offset, static_cast<uint32_t>(value_), image);
  67. DCHECK_EQ(kBit64, bitness_);
  68. return WriteAbs<uint64_t>(offset, value_, image);
  69. }
  70. /******** Abs32RvaExtractorWin32 ********/
  71. Abs32RvaExtractorWin32::Abs32RvaExtractorWin32(
  72. ConstBufferView image,
  73. AbsoluteAddress&& addr,
  74. const std::deque<offset_t>& abs32_locations,
  75. offset_t lo,
  76. offset_t hi)
  77. : image_(image), addr_(std::move(addr)) {
  78. CHECK_LE(lo, hi);
  79. auto find_and_check = [this](const std::deque<offset_t>& locations,
  80. offset_t offset) {
  81. auto it = std::lower_bound(locations.begin(), locations.end(), offset);
  82. // Ensure that |offset| does not straddle a reference body.
  83. CHECK(it == locations.begin() || offset - *(it - 1) >= addr_.width());
  84. return it;
  85. };
  86. cur_abs32_ = find_and_check(abs32_locations, lo);
  87. end_abs32_ = find_and_check(abs32_locations, hi);
  88. }
  89. Abs32RvaExtractorWin32::Abs32RvaExtractorWin32(Abs32RvaExtractorWin32&&) =
  90. default;
  91. Abs32RvaExtractorWin32::~Abs32RvaExtractorWin32() = default;
  92. absl::optional<Abs32RvaExtractorWin32::Unit> Abs32RvaExtractorWin32::GetNext() {
  93. while (cur_abs32_ < end_abs32_) {
  94. offset_t location = *(cur_abs32_++);
  95. if (!addr_.Read(location, image_))
  96. continue;
  97. rva_t target_rva = addr_.ToRva();
  98. if (target_rva == kInvalidRva)
  99. continue;
  100. return Unit{location, target_rva};
  101. }
  102. return absl::nullopt;
  103. }
  104. /******** Abs32ReaderWin32 ********/
  105. Abs32ReaderWin32::Abs32ReaderWin32(Abs32RvaExtractorWin32&& abs32_rva_extractor,
  106. const AddressTranslator& translator)
  107. : abs32_rva_extractor_(std::move(abs32_rva_extractor)),
  108. target_rva_to_offset_(translator) {}
  109. Abs32ReaderWin32::~Abs32ReaderWin32() = default;
  110. absl::optional<Reference> Abs32ReaderWin32::GetNext() {
  111. for (auto unit = abs32_rva_extractor_.GetNext(); unit.has_value();
  112. unit = abs32_rva_extractor_.GetNext()) {
  113. offset_t location = unit->location;
  114. offset_t unsafe_target = target_rva_to_offset_.Convert(unit->target_rva);
  115. if (unsafe_target != kInvalidOffset)
  116. return Reference{location, unsafe_target};
  117. }
  118. return absl::nullopt;
  119. }
  120. /******** Abs32WriterWin32 ********/
  121. Abs32WriterWin32::Abs32WriterWin32(MutableBufferView image,
  122. AbsoluteAddress&& addr,
  123. const AddressTranslator& translator)
  124. : image_(image),
  125. addr_(std::move(addr)),
  126. target_offset_to_rva_(translator) {}
  127. Abs32WriterWin32::~Abs32WriterWin32() = default;
  128. void Abs32WriterWin32::PutNext(Reference ref) {
  129. rva_t target_rva = target_offset_to_rva_.Convert(ref.target);
  130. if (target_rva != kInvalidRva) {
  131. addr_.FromRva(target_rva);
  132. addr_.Write(ref.location, &image_);
  133. }
  134. }
  135. /******** Exported Functions ********/
  136. size_t RemoveUntranslatableAbs32(ConstBufferView image,
  137. AbsoluteAddress&& addr,
  138. const AddressTranslator& translator,
  139. std::deque<offset_t>* locations) {
  140. AddressTranslator::RvaToOffsetCache target_rva_checker(translator);
  141. Abs32RvaExtractorWin32 extractor(image, std::move(addr), *locations, 0,
  142. image.size());
  143. Abs32ReaderWin32 reader(std::move(extractor), translator);
  144. std::deque<offset_t>::iterator write_it = locations->begin();
  145. // |reader| reads |locations| while |write_it| modifies it. However, there's
  146. // no conflict since read occurs before write, and can skip ahead.
  147. for (auto ref = reader.GetNext(); ref.has_value(); ref = reader.GetNext())
  148. *(write_it++) = ref->location;
  149. DCHECK(write_it <= locations->end());
  150. size_t num_removed = locations->end() - write_it;
  151. locations->erase(write_it, locations->end());
  152. return num_removed;
  153. }
  154. size_t RemoveOverlappingAbs32Locations(uint32_t width,
  155. std::deque<offset_t>* locations) {
  156. if (locations->size() <= 1)
  157. return 0;
  158. auto slow = locations->begin();
  159. auto fast = locations->begin() + 1;
  160. for (;;) {
  161. // Find next good location.
  162. while (fast != locations->end() && *fast - *slow < width)
  163. ++fast;
  164. // Advance |slow|. For the last iteration this becomes the new sentinel.
  165. ++slow;
  166. if (fast == locations->end())
  167. break;
  168. // Compactify good locations (potentially overwrite bad locations).
  169. if (slow != fast)
  170. *slow = *fast;
  171. ++fast;
  172. }
  173. size_t num_removed = locations->end() - slow;
  174. locations->erase(slow, locations->end());
  175. return num_removed;
  176. }
  177. } // namespace zucchini