Paul Robinson | 17536b9 | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 1 | //===- DWARFDataExtractor.cpp ---------------------------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" |
Rafael Auler | 86fb7bf | 2018-03-08 00:46:53 +0000 | [diff] [blame^] | 11 | #include "llvm/BinaryFormat/Dwarf.h" |
Rafael Espindola | c398e67 | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 12 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
Paul Robinson | 17536b9 | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 13 | |
| 14 | using namespace llvm; |
| 15 | |
| 16 | uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, |
| 17 | uint64_t *SecNdx) const { |
George Rimar | 2f95c8b | 2017-09-04 10:30:39 +0000 | [diff] [blame] | 18 | if (SecNdx) |
| 19 | *SecNdx = -1ULL; |
Rafael Espindola | c398e67 | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 20 | if (!Section) |
Paul Robinson | 17536b9 | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 21 | return getUnsigned(Off, Size); |
Rafael Espindola | c398e67 | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 22 | Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off); |
| 23 | if (!Rel) |
Paul Robinson | 17536b9 | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 24 | return getUnsigned(Off, Size); |
| 25 | if (SecNdx) |
Rafael Espindola | c398e67 | 2017-07-19 22:27:28 +0000 | [diff] [blame] | 26 | *SecNdx = Rel->SectionIndex; |
| 27 | return getUnsigned(Off, Size) + Rel->Value; |
Paul Robinson | 17536b9 | 2017-06-29 16:52:08 +0000 | [diff] [blame] | 28 | } |
Rafael Auler | 86fb7bf | 2018-03-08 00:46:53 +0000 | [diff] [blame^] | 29 | |
| 30 | Optional<uint64_t> |
| 31 | DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding, |
| 32 | uint64_t PCRelOffset) const { |
| 33 | if (Encoding == dwarf::DW_EH_PE_omit) |
| 34 | return None; |
| 35 | |
| 36 | uint64_t Result = 0; |
| 37 | uint32_t OldOffset = *Offset; |
| 38 | // First get value |
| 39 | switch (Encoding & 0x0F) { |
| 40 | case dwarf::DW_EH_PE_absptr: |
| 41 | switch (getAddressSize()) { |
| 42 | case 2: |
| 43 | case 4: |
| 44 | case 8: |
| 45 | Result = getUnsigned(Offset, getAddressSize()); |
| 46 | break; |
| 47 | default: |
| 48 | return None; |
| 49 | } |
| 50 | break; |
| 51 | case dwarf::DW_EH_PE_uleb128: |
| 52 | Result = getULEB128(Offset); |
| 53 | break; |
| 54 | case dwarf::DW_EH_PE_sleb128: |
| 55 | Result = getSLEB128(Offset); |
| 56 | break; |
| 57 | case dwarf::DW_EH_PE_udata2: |
| 58 | Result = getUnsigned(Offset, 2); |
| 59 | break; |
| 60 | case dwarf::DW_EH_PE_udata4: |
| 61 | Result = getUnsigned(Offset, 4); |
| 62 | break; |
| 63 | case dwarf::DW_EH_PE_udata8: |
| 64 | Result = getUnsigned(Offset, 8); |
| 65 | break; |
| 66 | case dwarf::DW_EH_PE_sdata2: |
| 67 | Result = getSigned(Offset, 2); |
| 68 | break; |
| 69 | case dwarf::DW_EH_PE_sdata4: |
| 70 | Result = getSigned(Offset, 4); |
| 71 | break; |
| 72 | case dwarf::DW_EH_PE_sdata8: |
| 73 | Result = getSigned(Offset, 8); |
| 74 | break; |
| 75 | default: |
| 76 | return None; |
| 77 | } |
| 78 | // Then add relative offset, if required |
| 79 | switch (Encoding & 0x70) { |
| 80 | case dwarf::DW_EH_PE_absptr: |
| 81 | // do nothing |
| 82 | break; |
| 83 | case dwarf::DW_EH_PE_pcrel: |
| 84 | Result += PCRelOffset; |
| 85 | break; |
| 86 | case dwarf::DW_EH_PE_datarel: |
| 87 | case dwarf::DW_EH_PE_textrel: |
| 88 | case dwarf::DW_EH_PE_funcrel: |
| 89 | case dwarf::DW_EH_PE_aligned: |
| 90 | default: |
| 91 | *Offset = OldOffset; |
| 92 | return None; |
| 93 | } |
| 94 | |
| 95 | return Result; |
| 96 | } |