DataExtractor.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. //===-- DataExtractor.cpp -------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Support/DataExtractor.h"
  9. #include "llvm/Support/Errc.h"
  10. #include "llvm/Support/ErrorHandling.h"
  11. #include "llvm/Support/Host.h"
  12. #include "llvm/Support/LEB128.h"
  13. #include "llvm/Support/SwapByteOrder.h"
  14. using namespace llvm;
  15. static void unexpectedEndReached(Error *E) {
  16. if (E)
  17. *E = createStringError(errc::illegal_byte_sequence,
  18. "unexpected end of data");
  19. }
  20. static bool isError(Error *E) { return E && *E; }
  21. template <typename T>
  22. static T getU(uint64_t *offset_ptr, const DataExtractor *de,
  23. bool isLittleEndian, const char *Data, llvm::Error *Err) {
  24. ErrorAsOutParameter ErrAsOut(Err);
  25. T val = 0;
  26. if (isError(Err))
  27. return val;
  28. uint64_t offset = *offset_ptr;
  29. if (!de->isValidOffsetForDataOfSize(offset, sizeof(T))) {
  30. unexpectedEndReached(Err);
  31. return val;
  32. }
  33. std::memcpy(&val, &Data[offset], sizeof(val));
  34. if (sys::IsLittleEndianHost != isLittleEndian)
  35. sys::swapByteOrder(val);
  36. // Advance the offset
  37. *offset_ptr += sizeof(val);
  38. return val;
  39. }
  40. template <typename T>
  41. static T *getUs(uint64_t *offset_ptr, T *dst, uint32_t count,
  42. const DataExtractor *de, bool isLittleEndian, const char *Data,
  43. llvm::Error *Err) {
  44. ErrorAsOutParameter ErrAsOut(Err);
  45. if (isError(Err))
  46. return nullptr;
  47. uint64_t offset = *offset_ptr;
  48. if (!de->isValidOffsetForDataOfSize(offset, sizeof(*dst) * count)) {
  49. unexpectedEndReached(Err);
  50. return nullptr;
  51. }
  52. for (T *value_ptr = dst, *end = dst + count; value_ptr != end;
  53. ++value_ptr, offset += sizeof(*dst))
  54. *value_ptr = getU<T>(offset_ptr, de, isLittleEndian, Data, Err);
  55. // Advance the offset
  56. *offset_ptr = offset;
  57. // Return a non-NULL pointer to the converted data as an indicator of
  58. // success
  59. return dst;
  60. }
  61. uint8_t DataExtractor::getU8(uint64_t *offset_ptr, llvm::Error *Err) const {
  62. return getU<uint8_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
  63. }
  64. uint8_t *
  65. DataExtractor::getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const {
  66. return getUs<uint8_t>(offset_ptr, dst, count, this, IsLittleEndian,
  67. Data.data(), nullptr);
  68. }
  69. uint8_t *DataExtractor::getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const {
  70. return getUs<uint8_t>(&C.Offset, Dst, Count, this, IsLittleEndian,
  71. Data.data(), &C.Err);
  72. }
  73. uint16_t DataExtractor::getU16(uint64_t *offset_ptr, llvm::Error *Err) const {
  74. return getU<uint16_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
  75. }
  76. uint16_t *DataExtractor::getU16(uint64_t *offset_ptr, uint16_t *dst,
  77. uint32_t count) const {
  78. return getUs<uint16_t>(offset_ptr, dst, count, this, IsLittleEndian,
  79. Data.data(), nullptr);
  80. }
  81. uint32_t DataExtractor::getU24(uint64_t *offset_ptr) const {
  82. uint24_t ExtractedVal =
  83. getU<uint24_t>(offset_ptr, this, IsLittleEndian, Data.data(), nullptr);
  84. // The 3 bytes are in the correct byte order for the host.
  85. return ExtractedVal.getAsUint32(sys::IsLittleEndianHost);
  86. }
  87. uint32_t DataExtractor::getU32(uint64_t *offset_ptr, llvm::Error *Err) const {
  88. return getU<uint32_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
  89. }
  90. uint32_t *DataExtractor::getU32(uint64_t *offset_ptr, uint32_t *dst,
  91. uint32_t count) const {
  92. return getUs<uint32_t>(offset_ptr, dst, count, this, IsLittleEndian,
  93. Data.data(), nullptr);
  94. }
  95. uint64_t DataExtractor::getU64(uint64_t *offset_ptr, llvm::Error *Err) const {
  96. return getU<uint64_t>(offset_ptr, this, IsLittleEndian, Data.data(), Err);
  97. }
  98. uint64_t *DataExtractor::getU64(uint64_t *offset_ptr, uint64_t *dst,
  99. uint32_t count) const {
  100. return getUs<uint64_t>(offset_ptr, dst, count, this, IsLittleEndian,
  101. Data.data(), nullptr);
  102. }
  103. uint64_t DataExtractor::getUnsigned(uint64_t *offset_ptr, uint32_t byte_size,
  104. llvm::Error *Err) const {
  105. switch (byte_size) {
  106. case 1:
  107. return getU8(offset_ptr, Err);
  108. case 2:
  109. return getU16(offset_ptr, Err);
  110. case 4:
  111. return getU32(offset_ptr, Err);
  112. case 8:
  113. return getU64(offset_ptr, Err);
  114. }
  115. llvm_unreachable("getUnsigned unhandled case!");
  116. }
  117. int64_t
  118. DataExtractor::getSigned(uint64_t *offset_ptr, uint32_t byte_size) const {
  119. switch (byte_size) {
  120. case 1:
  121. return (int8_t)getU8(offset_ptr);
  122. case 2:
  123. return (int16_t)getU16(offset_ptr);
  124. case 4:
  125. return (int32_t)getU32(offset_ptr);
  126. case 8:
  127. return (int64_t)getU64(offset_ptr);
  128. }
  129. llvm_unreachable("getSigned unhandled case!");
  130. }
  131. const char *DataExtractor::getCStr(uint64_t *offset_ptr) const {
  132. uint64_t offset = *offset_ptr;
  133. StringRef::size_type pos = Data.find('\0', offset);
  134. if (pos != StringRef::npos) {
  135. *offset_ptr = pos + 1;
  136. return Data.data() + offset;
  137. }
  138. return nullptr;
  139. }
  140. StringRef DataExtractor::getCStrRef(uint64_t *offset_ptr) const {
  141. uint64_t Start = *offset_ptr;
  142. StringRef::size_type Pos = Data.find('\0', Start);
  143. if (Pos != StringRef::npos) {
  144. *offset_ptr = Pos + 1;
  145. return StringRef(Data.data() + Start, Pos - Start);
  146. }
  147. return StringRef();
  148. }
  149. uint64_t DataExtractor::getULEB128(uint64_t *offset_ptr,
  150. llvm::Error *Err) const {
  151. assert(*offset_ptr <= Data.size());
  152. ErrorAsOutParameter ErrAsOut(Err);
  153. if (isError(Err))
  154. return 0;
  155. const char *error;
  156. unsigned bytes_read;
  157. uint64_t result = decodeULEB128(
  158. reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,
  159. reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error);
  160. if (error) {
  161. if (Err)
  162. *Err = createStringError(errc::illegal_byte_sequence, error);
  163. return 0;
  164. }
  165. *offset_ptr += bytes_read;
  166. return result;
  167. }
  168. int64_t DataExtractor::getSLEB128(uint64_t *offset_ptr) const {
  169. assert(*offset_ptr <= Data.size());
  170. const char *error;
  171. unsigned bytes_read;
  172. int64_t result = decodeSLEB128(
  173. reinterpret_cast<const uint8_t *>(Data.data() + *offset_ptr), &bytes_read,
  174. reinterpret_cast<const uint8_t *>(Data.data() + Data.size()), &error);
  175. if (error)
  176. return 0;
  177. *offset_ptr += bytes_read;
  178. return result;
  179. }
  180. void DataExtractor::skip(Cursor &C, uint64_t Length) const {
  181. ErrorAsOutParameter ErrAsOut(&C.Err);
  182. if (isError(&C.Err))
  183. return;
  184. if (isValidOffsetForDataOfSize(C.Offset, Length))
  185. C.Offset += Length;
  186. else
  187. unexpectedEndReached(&C.Err);
  188. }