DWARFDataExtractor.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //===- DWARFDataExtractor.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/DebugInfo/DWARF/DWARFDataExtractor.h"
  9. #include "llvm/DebugInfo/DWARF/DWARFObject.h"
  10. #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
  11. #include "llvm/Support/Errc.h"
  12. using namespace llvm;
  13. std::pair<uint64_t, dwarf::DwarfFormat>
  14. DWARFDataExtractor::getInitialLength(uint64_t *Off, Error *Err) const {
  15. ErrorAsOutParameter ErrAsOut(Err);
  16. if (Err && *Err)
  17. return {0, dwarf::DWARF32};
  18. Cursor C(*Off);
  19. uint64_t Length = getRelocatedValue(C, 4);
  20. dwarf::DwarfFormat Format = dwarf::DWARF32;
  21. if (Length == dwarf::DW_LENGTH_DWARF64) {
  22. Length = getRelocatedValue(C, 8);
  23. Format = dwarf::DWARF64;
  24. } else if (Length >= dwarf::DW_LENGTH_lo_reserved) {
  25. cantFail(C.takeError());
  26. if (Err)
  27. *Err = createStringError(
  28. errc::invalid_argument,
  29. "unsupported reserved unit length of value 0x%8.8" PRIx64, Length);
  30. return {0, dwarf::DWARF32};
  31. }
  32. if (C) {
  33. *Off = C.tell();
  34. return {Length, Format};
  35. }
  36. if (Err)
  37. *Err = C.takeError();
  38. else
  39. consumeError(C.takeError());
  40. return {0, dwarf::DWARF32};
  41. }
  42. uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
  43. uint64_t *SecNdx,
  44. Error *Err) const {
  45. if (SecNdx)
  46. *SecNdx = object::SectionedAddress::UndefSection;
  47. if (!Section)
  48. return getUnsigned(Off, Size, Err);
  49. ErrorAsOutParameter ErrAsOut(Err);
  50. std::optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
  51. uint64_t LocData = getUnsigned(Off, Size, Err);
  52. if (!E || (Err && *Err))
  53. return LocData;
  54. if (SecNdx)
  55. *SecNdx = E->SectionIndex;
  56. uint64_t R =
  57. object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData);
  58. if (E->Reloc2)
  59. R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R);
  60. return R;
  61. }
  62. std::optional<uint64_t>
  63. DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
  64. uint64_t PCRelOffset) const {
  65. if (Encoding == dwarf::DW_EH_PE_omit)
  66. return std::nullopt;
  67. uint64_t Result = 0;
  68. uint64_t OldOffset = *Offset;
  69. // First get value
  70. switch (Encoding & 0x0F) {
  71. case dwarf::DW_EH_PE_absptr:
  72. switch (getAddressSize()) {
  73. case 2:
  74. case 4:
  75. case 8:
  76. Result = getUnsigned(Offset, getAddressSize());
  77. break;
  78. default:
  79. return std::nullopt;
  80. }
  81. break;
  82. case dwarf::DW_EH_PE_uleb128:
  83. Result = getULEB128(Offset);
  84. break;
  85. case dwarf::DW_EH_PE_sleb128:
  86. Result = getSLEB128(Offset);
  87. break;
  88. case dwarf::DW_EH_PE_udata2:
  89. Result = getUnsigned(Offset, 2);
  90. break;
  91. case dwarf::DW_EH_PE_udata4:
  92. Result = getUnsigned(Offset, 4);
  93. break;
  94. case dwarf::DW_EH_PE_udata8:
  95. Result = getUnsigned(Offset, 8);
  96. break;
  97. case dwarf::DW_EH_PE_sdata2:
  98. Result = getSigned(Offset, 2);
  99. break;
  100. case dwarf::DW_EH_PE_sdata4:
  101. Result = SignExtend64<32>(getRelocatedValue(4, Offset));
  102. break;
  103. case dwarf::DW_EH_PE_sdata8:
  104. Result = getRelocatedValue(8, Offset);
  105. break;
  106. default:
  107. return std::nullopt;
  108. }
  109. // Then add relative offset, if required
  110. switch (Encoding & 0x70) {
  111. case dwarf::DW_EH_PE_absptr:
  112. // do nothing
  113. break;
  114. case dwarf::DW_EH_PE_pcrel:
  115. Result += PCRelOffset;
  116. break;
  117. case dwarf::DW_EH_PE_datarel:
  118. case dwarf::DW_EH_PE_textrel:
  119. case dwarf::DW_EH_PE_funcrel:
  120. case dwarf::DW_EH_PE_aligned:
  121. default:
  122. *Offset = OldOffset;
  123. return std::nullopt;
  124. }
  125. return Result;
  126. }