image_utils.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2015 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 COURGETTE_IMAGE_UTILS_H_
  5. #define COURGETTE_IMAGE_UTILS_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <iterator>
  9. #include <vector>
  10. // COURGETTE_HISTOGRAM_TARGETS prints out a histogram of how frequently
  11. // different target addresses are referenced. Purely for debugging.
  12. #define COURGETTE_HISTOGRAM_TARGETS 0
  13. namespace courgette {
  14. // There are several ways to reason about addresses in an image:
  15. // - File Offset: Position relative to start of image.
  16. // - VA (Virtual Address): Virtual memory address of a loaded image. This is
  17. // subject to relocation by the OS.
  18. // - RVA (Relative Virtual Address): VA relative to some base address. This is
  19. // the preferred way to specify pointers in an image.
  20. //
  21. // In Courgette we consider two types of addresses:
  22. // - abs32: In an image these are directly stored as VA whose locations are
  23. // stored in the relocation table.
  24. // - rel32: In an image these appear in branch/call opcodes, and are represented
  25. // as offsets from an instruction address.
  26. using RVA = uint32_t;
  27. const RVA kUnassignedRVA = 0xFFFFFFFFU;
  28. const RVA kNoRVA = 0xFFFFFFFFU;
  29. using FileOffset = size_t;
  30. const FileOffset kNoFileOffset = UINTPTR_MAX;
  31. // An interface translate and read addresses. The main conversion path is:
  32. // (1) Location RVA.
  33. // (2) Location FileOffset.
  34. // (3) Pointer in image.
  35. // (4) Target VA (32-bit or 64-bit).
  36. // (5) Target RVA (32-bit).
  37. // For abs32, we get (1) from relocation table, and convert to (5).
  38. // For rel32, we get (2) from scanning opcode, and convert to (1).
  39. class AddressTranslator {
  40. public:
  41. // (2) -> (1): Returns the RVA corresponding to |file_offset|, or kNoRVA if
  42. // nonexistent.
  43. virtual RVA FileOffsetToRVA(FileOffset file_offset) const = 0;
  44. // (1) -> (2): Returns the file offset corresponding to |rva|, or
  45. // kNoFileOffset if nonexistent.
  46. virtual FileOffset RVAToFileOffset(RVA rva) const = 0;
  47. // (2) -> (3): Returns image data pointer correspnoding to |file_offset|.
  48. // Assumes 0 <= |file_offset| <= image size.
  49. // If |file_offset| == image size, then the resulting pointer is an end bound
  50. // for iteration, and should not be dereferenced.
  51. virtual const uint8_t* FileOffsetToPointer(FileOffset file_offset) const = 0;
  52. // (1) -> (3): Returns the pointer to the image data for |rva|, or null if
  53. // |rva| is invalid.
  54. virtual const uint8_t* RVAToPointer(RVA rva) const = 0;
  55. // (3) -> (5): Returns the target RVA located at |p|, where |p| is a pointer
  56. // to image data.
  57. virtual RVA PointerToTargetRVA(const uint8_t* p) const = 0;
  58. };
  59. // A Label is a symbolic reference to an address. Unlike a conventional
  60. // assembly language, we always know the address. The address will later be
  61. // stored in a table and the Label will be replaced with the index into the
  62. // table.
  63. // TODO(huangs): Make this a struct, and remove "_" from member names.
  64. class Label {
  65. public:
  66. enum : int { kNoIndex = -1 };
  67. explicit Label(RVA rva) : rva_(rva) {}
  68. Label(RVA rva, int index) : rva_(rva), index_(index) {}
  69. Label(RVA rva, int index, int32_t count)
  70. : rva_(rva), index_(index), count_(count) {}
  71. bool operator==(const Label& other) const {
  72. return rva_ == other.rva_ && index_ == other.index_ &&
  73. count_ == other.count_;
  74. }
  75. RVA rva_ = kUnassignedRVA; // Address referred to by the label.
  76. int index_ = kNoIndex; // Index of address in address table.
  77. int32_t count_ = 0;
  78. };
  79. // An interface for sequential visit of RVAs.
  80. // Use case: Translating from RVA locations to RVA targets is platform-specific,
  81. // and works differently for abs32 vs. rel32. A function that sequentually
  82. // visits RVA targets only requires an RvaVisitor. The caller can provide an
  83. // implementation that stores a fixed list of RVA locations, and translates each
  84. // to the matching RVA target on demand without extra storage.
  85. class RvaVisitor {
  86. public:
  87. virtual ~RvaVisitor() { }
  88. // Returns the number of remaining RVAs to visit.
  89. virtual size_t Remaining() const = 0;
  90. // Returns the current RVA.
  91. virtual RVA Get() const = 0;
  92. // Advances to the next RVA.
  93. virtual void Next() = 0;
  94. };
  95. // RvaVisitor whose data are backed by std::vector<T>. Translating from T to RVA
  96. // is should be implemented in Get().
  97. template <typename T>
  98. class VectorRvaVisitor : public RvaVisitor {
  99. public:
  100. // Assumes |v| does not change for the lifetime of this instance.
  101. explicit VectorRvaVisitor(const std::vector<T>& v)
  102. : it_(v.begin()), end_(v.end()) { }
  103. ~VectorRvaVisitor() override { }
  104. // RvaVisitor interfaces.
  105. size_t Remaining() const override { return std::distance(it_, end_); }
  106. virtual RVA Get() const override = 0;
  107. void Next() override { ++it_; }
  108. protected:
  109. typename std::vector<T>::const_iterator it_;
  110. typename std::vector<T>::const_iterator end_;
  111. };
  112. // RvaVisitor that simply stores a list of RVAs for traversal. For testing.
  113. class TrivialRvaVisitor : public VectorRvaVisitor<RVA> {
  114. public:
  115. explicit TrivialRvaVisitor(const std::vector<RVA>& rvas)
  116. : VectorRvaVisitor<RVA>(rvas) { }
  117. ~TrivialRvaVisitor() override { }
  118. // VectorRvaVisitor<RVA> interfaces.
  119. RVA Get() const override { return *it_; }
  120. };
  121. // These helper functions avoid the need for casts in the main code.
  122. inline uint16_t ReadU16(const uint8_t* address, size_t offset) {
  123. return *reinterpret_cast<const uint16_t*>(address + offset);
  124. }
  125. inline uint32_t ReadU32(const uint8_t* address, size_t offset) {
  126. return *reinterpret_cast<const uint32_t*>(address + offset);
  127. }
  128. inline uint64_t ReadU64(const uint8_t* address, size_t offset) {
  129. return *reinterpret_cast<const uint64_t*>(address + offset);
  130. }
  131. inline uint16_t Read16LittleEndian(const void* address) {
  132. return *reinterpret_cast<const uint16_t*>(address);
  133. }
  134. inline uint32_t Read32LittleEndian(const void* address) {
  135. return *reinterpret_cast<const uint32_t*>(address);
  136. }
  137. inline uint64_t Read64LittleEndian(const void* address) {
  138. return *reinterpret_cast<const uint64_t*>(address);
  139. }
  140. } // namespace courgette
  141. #endif // COURGETTE_IMAGE_UTILS_H_