xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===- DWARFDataExtractor.cpp ---------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
1081ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFObject.h"
1181ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
1281ad6265SDimitry Andric #include "llvm/Support/Errc.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric 
165ffd83dbSDimitry Andric std::pair<uint64_t, dwarf::DwarfFormat>
getInitialLength(uint64_t * Off,Error * Err) const175ffd83dbSDimitry Andric DWARFDataExtractor::getInitialLength(uint64_t *Off, Error *Err) const {
185ffd83dbSDimitry Andric   ErrorAsOutParameter ErrAsOut(Err);
195ffd83dbSDimitry Andric   if (Err && *Err)
205ffd83dbSDimitry Andric     return {0, dwarf::DWARF32};
215ffd83dbSDimitry Andric 
225ffd83dbSDimitry Andric   Cursor C(*Off);
235ffd83dbSDimitry Andric   uint64_t Length = getRelocatedValue(C, 4);
245ffd83dbSDimitry Andric   dwarf::DwarfFormat Format = dwarf::DWARF32;
255ffd83dbSDimitry Andric   if (Length == dwarf::DW_LENGTH_DWARF64) {
265ffd83dbSDimitry Andric     Length = getRelocatedValue(C, 8);
275ffd83dbSDimitry Andric     Format = dwarf::DWARF64;
285ffd83dbSDimitry Andric   } else if (Length >= dwarf::DW_LENGTH_lo_reserved) {
295ffd83dbSDimitry Andric     cantFail(C.takeError());
305ffd83dbSDimitry Andric     if (Err)
315ffd83dbSDimitry Andric       *Err = createStringError(
325ffd83dbSDimitry Andric           errc::invalid_argument,
335ffd83dbSDimitry Andric           "unsupported reserved unit length of value 0x%8.8" PRIx64, Length);
345ffd83dbSDimitry Andric     return {0, dwarf::DWARF32};
355ffd83dbSDimitry Andric   }
365ffd83dbSDimitry Andric 
375ffd83dbSDimitry Andric   if (C) {
385ffd83dbSDimitry Andric     *Off = C.tell();
395ffd83dbSDimitry Andric     return {Length, Format};
405ffd83dbSDimitry Andric   }
415ffd83dbSDimitry Andric   if (Err)
425ffd83dbSDimitry Andric     *Err = C.takeError();
435ffd83dbSDimitry Andric   else
445ffd83dbSDimitry Andric     consumeError(C.takeError());
455ffd83dbSDimitry Andric   return {0, dwarf::DWARF32};
465ffd83dbSDimitry Andric }
475ffd83dbSDimitry Andric 
getRelocatedValue(uint32_t Size,uint64_t * Off,uint64_t * SecNdx,Error * Err) const488bcb0991SDimitry Andric uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
498bcb0991SDimitry Andric                                                uint64_t *SecNdx,
508bcb0991SDimitry Andric                                                Error *Err) const {
510b57cec5SDimitry Andric   if (SecNdx)
520b57cec5SDimitry Andric     *SecNdx = object::SectionedAddress::UndefSection;
530b57cec5SDimitry Andric   if (!Section)
548bcb0991SDimitry Andric     return getUnsigned(Off, Size, Err);
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric   ErrorAsOutParameter ErrAsOut(Err);
57*bdd1243dSDimitry Andric   std::optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
58e8d8bef9SDimitry Andric   uint64_t LocData = getUnsigned(Off, Size, Err);
595ffd83dbSDimitry Andric   if (!E || (Err && *Err))
60e8d8bef9SDimitry Andric     return LocData;
610b57cec5SDimitry Andric   if (SecNdx)
620b57cec5SDimitry Andric     *SecNdx = E->SectionIndex;
63e8d8bef9SDimitry Andric 
64e8d8bef9SDimitry Andric   uint64_t R =
65e8d8bef9SDimitry Andric       object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData);
660b57cec5SDimitry Andric   if (E->Reloc2)
67e8d8bef9SDimitry Andric     R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R);
680b57cec5SDimitry Andric   return R;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
71*bdd1243dSDimitry Andric std::optional<uint64_t>
getEncodedPointer(uint64_t * Offset,uint8_t Encoding,uint64_t PCRelOffset) const728bcb0991SDimitry Andric DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
730b57cec5SDimitry Andric                                       uint64_t PCRelOffset) const {
740b57cec5SDimitry Andric   if (Encoding == dwarf::DW_EH_PE_omit)
75*bdd1243dSDimitry Andric     return std::nullopt;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   uint64_t Result = 0;
788bcb0991SDimitry Andric   uint64_t OldOffset = *Offset;
790b57cec5SDimitry Andric   // First get value
800b57cec5SDimitry Andric   switch (Encoding & 0x0F) {
810b57cec5SDimitry Andric   case dwarf::DW_EH_PE_absptr:
820b57cec5SDimitry Andric     switch (getAddressSize()) {
830b57cec5SDimitry Andric     case 2:
840b57cec5SDimitry Andric     case 4:
850b57cec5SDimitry Andric     case 8:
860b57cec5SDimitry Andric       Result = getUnsigned(Offset, getAddressSize());
870b57cec5SDimitry Andric       break;
880b57cec5SDimitry Andric     default:
89*bdd1243dSDimitry Andric       return std::nullopt;
900b57cec5SDimitry Andric     }
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric   case dwarf::DW_EH_PE_uleb128:
930b57cec5SDimitry Andric     Result = getULEB128(Offset);
940b57cec5SDimitry Andric     break;
950b57cec5SDimitry Andric   case dwarf::DW_EH_PE_sleb128:
960b57cec5SDimitry Andric     Result = getSLEB128(Offset);
970b57cec5SDimitry Andric     break;
980b57cec5SDimitry Andric   case dwarf::DW_EH_PE_udata2:
990b57cec5SDimitry Andric     Result = getUnsigned(Offset, 2);
1000b57cec5SDimitry Andric     break;
1010b57cec5SDimitry Andric   case dwarf::DW_EH_PE_udata4:
1020b57cec5SDimitry Andric     Result = getUnsigned(Offset, 4);
1030b57cec5SDimitry Andric     break;
1040b57cec5SDimitry Andric   case dwarf::DW_EH_PE_udata8:
1050b57cec5SDimitry Andric     Result = getUnsigned(Offset, 8);
1060b57cec5SDimitry Andric     break;
1070b57cec5SDimitry Andric   case dwarf::DW_EH_PE_sdata2:
1080b57cec5SDimitry Andric     Result = getSigned(Offset, 2);
1090b57cec5SDimitry Andric     break;
1100b57cec5SDimitry Andric   case dwarf::DW_EH_PE_sdata4:
111e8d8bef9SDimitry Andric     Result = SignExtend64<32>(getRelocatedValue(4, Offset));
1120b57cec5SDimitry Andric     break;
1130b57cec5SDimitry Andric   case dwarf::DW_EH_PE_sdata8:
114e8d8bef9SDimitry Andric     Result = getRelocatedValue(8, Offset);
1150b57cec5SDimitry Andric     break;
1160b57cec5SDimitry Andric   default:
117*bdd1243dSDimitry Andric     return std::nullopt;
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric   // Then add relative offset, if required
1200b57cec5SDimitry Andric   switch (Encoding & 0x70) {
1210b57cec5SDimitry Andric   case dwarf::DW_EH_PE_absptr:
1220b57cec5SDimitry Andric     // do nothing
1230b57cec5SDimitry Andric     break;
1240b57cec5SDimitry Andric   case dwarf::DW_EH_PE_pcrel:
1250b57cec5SDimitry Andric     Result += PCRelOffset;
1260b57cec5SDimitry Andric     break;
1270b57cec5SDimitry Andric   case dwarf::DW_EH_PE_datarel:
1280b57cec5SDimitry Andric   case dwarf::DW_EH_PE_textrel:
1290b57cec5SDimitry Andric   case dwarf::DW_EH_PE_funcrel:
1300b57cec5SDimitry Andric   case dwarf::DW_EH_PE_aligned:
1310b57cec5SDimitry Andric   default:
1320b57cec5SDimitry Andric     *Offset = OldOffset;
133*bdd1243dSDimitry Andric     return std::nullopt;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   return Result;
1370b57cec5SDimitry Andric }
138