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