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