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 54 ErrorAsOutParameter ErrAsOut(Err); 55 Optional<RelocAddrEntry> E = Obj->find(*Section, *Off); 56 uint64_t LocData = getUnsigned(Off, Size, Err); 57 if (!E || (Err && *Err)) 58 return LocData; 59 if (SecNdx) 60 *SecNdx = E->SectionIndex; 61 62 uint64_t R = 63 object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData); 64 if (E->Reloc2) 65 R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R); 66 return R; 67 } 68 69 Optional<uint64_t> 70 DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding, 71 uint64_t PCRelOffset) const { 72 if (Encoding == dwarf::DW_EH_PE_omit) 73 return None; 74 75 uint64_t Result = 0; 76 uint64_t OldOffset = *Offset; 77 // First get value 78 switch (Encoding & 0x0F) { 79 case dwarf::DW_EH_PE_absptr: 80 switch (getAddressSize()) { 81 case 2: 82 case 4: 83 case 8: 84 Result = getUnsigned(Offset, getAddressSize()); 85 break; 86 default: 87 return None; 88 } 89 break; 90 case dwarf::DW_EH_PE_uleb128: 91 Result = getULEB128(Offset); 92 break; 93 case dwarf::DW_EH_PE_sleb128: 94 Result = getSLEB128(Offset); 95 break; 96 case dwarf::DW_EH_PE_udata2: 97 Result = getUnsigned(Offset, 2); 98 break; 99 case dwarf::DW_EH_PE_udata4: 100 Result = getUnsigned(Offset, 4); 101 break; 102 case dwarf::DW_EH_PE_udata8: 103 Result = getUnsigned(Offset, 8); 104 break; 105 case dwarf::DW_EH_PE_sdata2: 106 Result = getSigned(Offset, 2); 107 break; 108 case dwarf::DW_EH_PE_sdata4: 109 Result = SignExtend64<32>(getRelocatedValue(4, Offset)); 110 break; 111 case dwarf::DW_EH_PE_sdata8: 112 Result = getRelocatedValue(8, Offset); 113 break; 114 default: 115 return None; 116 } 117 // Then add relative offset, if required 118 switch (Encoding & 0x70) { 119 case dwarf::DW_EH_PE_absptr: 120 // do nothing 121 break; 122 case dwarf::DW_EH_PE_pcrel: 123 Result += PCRelOffset; 124 break; 125 case dwarf::DW_EH_PE_datarel: 126 case dwarf::DW_EH_PE_textrel: 127 case dwarf::DW_EH_PE_funcrel: 128 case dwarf::DW_EH_PE_aligned: 129 default: 130 *Offset = OldOffset; 131 return None; 132 } 133 134 return Result; 135 } 136