117536b93SPaul Robinson //===- DWARFDataExtractor.cpp ---------------------------------------------===//
217536b93SPaul Robinson //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617536b93SPaul Robinson //
717536b93SPaul Robinson //===----------------------------------------------------------------------===//
817536b93SPaul Robinson
917536b93SPaul Robinson #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
10290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFObject.h"
11290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
12290e4823Sserge-sans-paille #include "llvm/Support/Errc.h"
1317536b93SPaul Robinson
1417536b93SPaul Robinson using namespace llvm;
1517536b93SPaul Robinson
163c36d8daSPavel Labath std::pair<uint64_t, dwarf::DwarfFormat>
getInitialLength(uint64_t * Off,Error * Err) const173c36d8daSPavel Labath DWARFDataExtractor::getInitialLength(uint64_t *Off, Error *Err) const {
183c36d8daSPavel Labath ErrorAsOutParameter ErrAsOut(Err);
193c36d8daSPavel Labath if (Err && *Err)
203c36d8daSPavel Labath return {0, dwarf::DWARF32};
213c36d8daSPavel Labath
223c36d8daSPavel Labath Cursor C(*Off);
233c36d8daSPavel Labath uint64_t Length = getRelocatedValue(C, 4);
243c36d8daSPavel Labath dwarf::DwarfFormat Format = dwarf::DWARF32;
253c36d8daSPavel Labath if (Length == dwarf::DW_LENGTH_DWARF64) {
263c36d8daSPavel Labath Length = getRelocatedValue(C, 8);
273c36d8daSPavel Labath Format = dwarf::DWARF64;
283c36d8daSPavel Labath } else if (Length >= dwarf::DW_LENGTH_lo_reserved) {
293c36d8daSPavel Labath cantFail(C.takeError());
303c36d8daSPavel Labath if (Err)
313c36d8daSPavel Labath *Err = createStringError(
323c36d8daSPavel Labath errc::invalid_argument,
333c36d8daSPavel Labath "unsupported reserved unit length of value 0x%8.8" PRIx64, Length);
343c36d8daSPavel Labath return {0, dwarf::DWARF32};
353c36d8daSPavel Labath }
363c36d8daSPavel Labath
373c36d8daSPavel Labath if (C) {
383c36d8daSPavel Labath *Off = C.tell();
393c36d8daSPavel Labath return {Length, Format};
403c36d8daSPavel Labath }
413c36d8daSPavel Labath if (Err)
423c36d8daSPavel Labath *Err = C.takeError();
433c36d8daSPavel Labath else
443c36d8daSPavel Labath consumeError(C.takeError());
453c36d8daSPavel Labath return {0, dwarf::DWARF32};
463c36d8daSPavel Labath }
473c36d8daSPavel Labath
getRelocatedValue(uint32_t Size,uint64_t * Off,uint64_t * SecNdx,Error * Err) const48f5f35c5cSIgor Kudrin uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off,
49b1f29cecSPavel Labath uint64_t *SecNdx,
50b1f29cecSPavel Labath Error *Err) const {
512f95c8bcSGeorge Rimar if (SecNdx)
5277fc1f60SAlexey Lapshin *SecNdx = object::SectionedAddress::UndefSection;
53c398e67fSRafael Espindola if (!Section)
54b1f29cecSPavel Labath return getUnsigned(Off, Size, Err);
55122c50d5SPavel Labath
56122c50d5SPavel Labath ErrorAsOutParameter ErrAsOut(Err);
57c33511c8SFangrui Song std::optional<RelocAddrEntry> E = Obj->find(*Section, *Off);
589a99d23aSGeorgii Rymar uint64_t LocData = getUnsigned(Off, Size, Err);
59122c50d5SPavel Labath if (!E || (Err && *Err))
609a99d23aSGeorgii Rymar return LocData;
6117536b93SPaul Robinson if (SecNdx)
624597dce4SFangrui Song *SecNdx = E->SectionIndex;
639a99d23aSGeorgii Rymar
649a99d23aSGeorgii Rymar uint64_t R =
659a99d23aSGeorgii Rymar object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData);
6644deaf7eSAlex Bradbury if (E->Reloc2)
679a99d23aSGeorgii Rymar R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R);
6844deaf7eSAlex Bradbury return R;
6917536b93SPaul Robinson }
7086fb7bf2SRafael Auler
71*89fab98eSFangrui Song std::optional<uint64_t>
getEncodedPointer(uint64_t * Offset,uint8_t Encoding,uint64_t PCRelOffset) const72f5f35c5cSIgor Kudrin DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
7386fb7bf2SRafael Auler uint64_t PCRelOffset) const {
7486fb7bf2SRafael Auler if (Encoding == dwarf::DW_EH_PE_omit)
7511011599SKazu Hirata return std::nullopt;
7686fb7bf2SRafael Auler
7786fb7bf2SRafael Auler uint64_t Result = 0;
78f5f35c5cSIgor Kudrin uint64_t OldOffset = *Offset;
7986fb7bf2SRafael Auler // First get value
8086fb7bf2SRafael Auler switch (Encoding & 0x0F) {
8186fb7bf2SRafael Auler case dwarf::DW_EH_PE_absptr:
8286fb7bf2SRafael Auler switch (getAddressSize()) {
8386fb7bf2SRafael Auler case 2:
8486fb7bf2SRafael Auler case 4:
8586fb7bf2SRafael Auler case 8:
8686fb7bf2SRafael Auler Result = getUnsigned(Offset, getAddressSize());
8786fb7bf2SRafael Auler break;
8886fb7bf2SRafael Auler default:
8911011599SKazu Hirata return std::nullopt;
9086fb7bf2SRafael Auler }
9186fb7bf2SRafael Auler break;
9286fb7bf2SRafael Auler case dwarf::DW_EH_PE_uleb128:
9386fb7bf2SRafael Auler Result = getULEB128(Offset);
9486fb7bf2SRafael Auler break;
9586fb7bf2SRafael Auler case dwarf::DW_EH_PE_sleb128:
9686fb7bf2SRafael Auler Result = getSLEB128(Offset);
9786fb7bf2SRafael Auler break;
9886fb7bf2SRafael Auler case dwarf::DW_EH_PE_udata2:
9986fb7bf2SRafael Auler Result = getUnsigned(Offset, 2);
10086fb7bf2SRafael Auler break;
10186fb7bf2SRafael Auler case dwarf::DW_EH_PE_udata4:
10286fb7bf2SRafael Auler Result = getUnsigned(Offset, 4);
10386fb7bf2SRafael Auler break;
10486fb7bf2SRafael Auler case dwarf::DW_EH_PE_udata8:
10586fb7bf2SRafael Auler Result = getUnsigned(Offset, 8);
10686fb7bf2SRafael Auler break;
10786fb7bf2SRafael Auler case dwarf::DW_EH_PE_sdata2:
10886fb7bf2SRafael Auler Result = getSigned(Offset, 2);
10986fb7bf2SRafael Auler break;
11086fb7bf2SRafael Auler case dwarf::DW_EH_PE_sdata4:
1113ab0f53eSFangrui Song Result = SignExtend64<32>(getRelocatedValue(4, Offset));
11286fb7bf2SRafael Auler break;
11386fb7bf2SRafael Auler case dwarf::DW_EH_PE_sdata8:
1143ab0f53eSFangrui Song Result = getRelocatedValue(8, Offset);
11586fb7bf2SRafael Auler break;
11686fb7bf2SRafael Auler default:
11711011599SKazu Hirata return std::nullopt;
11886fb7bf2SRafael Auler }
11986fb7bf2SRafael Auler // Then add relative offset, if required
12086fb7bf2SRafael Auler switch (Encoding & 0x70) {
12186fb7bf2SRafael Auler case dwarf::DW_EH_PE_absptr:
12286fb7bf2SRafael Auler // do nothing
12386fb7bf2SRafael Auler break;
12486fb7bf2SRafael Auler case dwarf::DW_EH_PE_pcrel:
12586fb7bf2SRafael Auler Result += PCRelOffset;
12686fb7bf2SRafael Auler break;
12786fb7bf2SRafael Auler case dwarf::DW_EH_PE_datarel:
12886fb7bf2SRafael Auler case dwarf::DW_EH_PE_textrel:
12986fb7bf2SRafael Auler case dwarf::DW_EH_PE_funcrel:
13086fb7bf2SRafael Auler case dwarf::DW_EH_PE_aligned:
13186fb7bf2SRafael Auler default:
13286fb7bf2SRafael Auler *Offset = OldOffset;
13311011599SKazu Hirata return std::nullopt;
13486fb7bf2SRafael Auler }
13586fb7bf2SRafael Auler
13686fb7bf2SRafael Auler return Result;
13786fb7bf2SRafael Auler }
138