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