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/BinaryFormat/Dwarf.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 
13 using namespace llvm;
14 
15 uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off,
16                                                uint64_t *SecNdx) const {
17   if (SecNdx)
18     *SecNdx = object::SectionedAddress::UndefSection;
19   if (!Section)
20     return getUnsigned(Off, Size);
21   Optional<RelocAddrEntry> Rel = Obj->find(*Section, *Off);
22   if (!Rel)
23     return getUnsigned(Off, Size);
24   if (SecNdx)
25     *SecNdx = Rel->SectionIndex;
26   return getUnsigned(Off, Size) + Rel->Value;
27 }
28 
29 Optional<uint64_t>
30 DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
31                                       uint64_t PCRelOffset) const {
32   if (Encoding == dwarf::DW_EH_PE_omit)
33     return None;
34 
35   uint64_t Result = 0;
36   uint32_t OldOffset = *Offset;
37   // First get value
38   switch (Encoding & 0x0F) {
39   case dwarf::DW_EH_PE_absptr:
40     switch (getAddressSize()) {
41     case 2:
42     case 4:
43     case 8:
44       Result = getUnsigned(Offset, getAddressSize());
45       break;
46     default:
47       return None;
48     }
49     break;
50   case dwarf::DW_EH_PE_uleb128:
51     Result = getULEB128(Offset);
52     break;
53   case dwarf::DW_EH_PE_sleb128:
54     Result = getSLEB128(Offset);
55     break;
56   case dwarf::DW_EH_PE_udata2:
57     Result = getUnsigned(Offset, 2);
58     break;
59   case dwarf::DW_EH_PE_udata4:
60     Result = getUnsigned(Offset, 4);
61     break;
62   case dwarf::DW_EH_PE_udata8:
63     Result = getUnsigned(Offset, 8);
64     break;
65   case dwarf::DW_EH_PE_sdata2:
66     Result = getSigned(Offset, 2);
67     break;
68   case dwarf::DW_EH_PE_sdata4:
69     Result = getSigned(Offset, 4);
70     break;
71   case dwarf::DW_EH_PE_sdata8:
72     Result = getSigned(Offset, 8);
73     break;
74   default:
75     return None;
76   }
77   // Then add relative offset, if required
78   switch (Encoding & 0x70) {
79   case dwarf::DW_EH_PE_absptr:
80     // do nothing
81     break;
82   case dwarf::DW_EH_PE_pcrel:
83     Result += PCRelOffset;
84     break;
85   case dwarf::DW_EH_PE_datarel:
86   case dwarf::DW_EH_PE_textrel:
87   case dwarf::DW_EH_PE_funcrel:
88   case dwarf::DW_EH_PE_aligned:
89   default:
90     *Offset = OldOffset;
91     return None;
92   }
93 
94   return Result;
95 }
96