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