LLVM 24.0.0git
AddressesMap.h
Go to the documentation of this file.
1//===- AddressesMap.h -------------------------------------------*- C++ -*-===//
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#ifndef LLVM_DWARFLINKER_ADDRESSESMAP_H
10#define LLVM_DWARFLINKER_ADDRESSESMAP_H
11
17#include <cstdint>
18
19namespace llvm {
20namespace dwarf_linker {
21
22/// Mapped value in the address map is the offset to apply to the
23/// linked address.
25
26/// AddressesMap represents information about valid addresses used
27/// by debug information. Valid addresses are those which points to
28/// live code sections. i.e. relocations for these addresses point
29/// into sections which would be/are placed into resulting binary.
31public:
32 virtual ~AddressesMap() = default;
33
34 /// Checks that there are valid relocations in the .debug_info
35 /// section.
36 virtual bool hasValidRelocs() = 0;
37
38 /// Checks that the specified DWARF expression operand \p Op references live
39 /// code section and returns the relocation adjustment value (to get the
40 /// linked address this value might be added to the source expression operand
41 /// address). Print debug output if \p Verbose is true.
42 /// \returns relocation adjustment value or std::nullopt if there is no
43 /// corresponding live address.
44 virtual std::optional<int64_t> getExprOpAddressRelocAdjustment(
45 DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
46 uint64_t EndOffset, bool Verbose) = 0;
47
48 /// Checks that the specified subprogram \p DIE references the live code
49 /// section and returns the relocation adjustment value (to get the linked
50 /// address this value might be added to the source subprogram address).
51 /// Allowed kinds of input DIE: DW_TAG_subprogram, DW_TAG_label.
52 /// Print debug output if \p Verbose is true.
53 /// \returns relocation adjustment value or std::nullopt if there is no
54 /// corresponding live address.
55 virtual std::optional<int64_t>
57
58 // Returns the library install name associated to the AddessesMap.
59 virtual std::optional<StringRef> getLibraryInstallName() = 0;
60
61 /// Apply the valid relocations to the buffer \p Data, taking into
62 /// account that Data is at \p BaseOffset in the .debug_info section.
63 ///
64 /// \returns true whether any reloc has been applied.
66 bool IsLittleEndian) = 0;
67
68 /// Check if the linker needs to gather and save relocation info.
69 virtual bool needToSaveValidRelocs() = 0;
70
71 /// Update and save relocation values to be serialized
72 virtual void updateAndSaveValidRelocs(bool IsDWARF5,
73 uint64_t OriginalUnitOffset,
74 int64_t LinkedOffset,
75 uint64_t StartOffset,
76 uint64_t EndOffset) = 0;
77
78 /// Update the valid relocations that used OriginalUnitOffset as the compile
79 /// unit offset, and update their values to reflect OutputUnitOffset.
80 virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
81 uint64_t OutputUnitOffset) = 0;
82
83 /// Erases all data.
84 virtual void clear() = 0;
85
86 /// The extent the linker gave a symbol, in source address space.
93
94 /// Returns the symbol range [LowPC, HighPC) containing \p Addr, if known.
95 virtual std::optional<SymbolRange> getSymbolRangeForAddress(uint64_t Addr) {
96 return std::nullopt;
97 }
98
99 /// Returns the linked address of the first symbol placed at or after
100 /// \p LinkedAddr, if one is known.
101 virtual std::optional<uint64_t>
103 return std::nullopt;
104 }
105
106 /// Constrains the end of the code range starting at \p LowPC, whose addresses
107 /// shift by \p Adjustment in the output. \p HighPC is an address, not a
108 /// length.
109 ///
110 /// The linker places symbols independently, so a range overrunning the symbol
111 /// it starts in can cover a different one once linked. Only that overlap is
112 /// repaired.
114 int64_t Adjustment) {
115 std::optional<SymbolRange> Symbol = getSymbolRangeForAddress(LowPC);
116 if (!Symbol)
117 return HighPC;
118 assert(Symbol->LowPC <= LowPC && LowPC < Symbol->HighPC &&
119 "Symbol range must contain the address it was looked up for");
120 uint64_t LinkedSymbolHighPC = Symbol->HighPC + Adjustment;
121 assert(LinkedSymbolHighPC > Symbol->LowPC + Adjustment &&
122 "Adjusting a symbol range must preserve its order");
123 std::optional<uint64_t> NextStart =
124 getNextLinkedSymbolStart(LinkedSymbolHighPC);
125 if (!NextStart)
126 return HighPC;
127 assert(*NextStart >= LinkedSymbolHighPC &&
128 "A range must never be cut short of its own symbol");
129 return std::min(HighPC, *NextStart - Adjustment);
130 }
131
132 /// This function checks whether variable has DWARF expression containing
133 /// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
134 /// \returns first is true if the expression has an operation referencing an
135 /// address.
136 /// second is the relocation adjustment value if the live address is
137 /// referenced.
138 std::pair<bool, std::optional<int64_t>>
140 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
141 DIE.getTag() == dwarf::DW_TAG_constant) &&
142 "Wrong type of input die");
143
144 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
145
146 // Check if DIE has DW_AT_location attribute.
147 DWARFUnit *U = DIE.getDwarfUnit();
148 std::optional<uint32_t> LocationIdx =
149 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
150 if (!LocationIdx)
151 return std::make_pair(false, std::nullopt);
152
153 // Get offset to the DW_AT_location attribute.
154 uint64_t AttrOffset =
155 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
156
157 // Get value of the DW_AT_location attribute.
158 std::optional<DWARFFormValue> LocationValue =
159 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
160 if (!LocationValue)
161 return std::make_pair(false, std::nullopt);
162
163 // Check that DW_AT_location attribute is of 'exprloc' class.
164 // Handling value of location expressions for attributes of 'loclist'
165 // class is not implemented yet.
166 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
167 if (!Expr)
168 return std::make_pair(false, std::nullopt);
169
170 // Parse 'exprloc' expression.
171 DataExtractor Data(*Expr, U->getContext().isLittleEndian());
172 DWARFExpression Expression(Data, U->getAddressByteSize(),
173 U->getFormParams().Format);
174
175 bool HasLocationAddress = false;
176 uint64_t CurExprOffset = 0;
177 for (DWARFExpression::iterator It = Expression.begin();
178 It != Expression.end(); ++It) {
179 DWARFExpression::iterator NextIt = It;
180 ++NextIt;
181
182 const DWARFExpression::Operation &Op = *It;
183 switch (Op.getCode()) {
184 case dwarf::DW_OP_const2u:
185 case dwarf::DW_OP_const4u:
186 case dwarf::DW_OP_const8u:
187 case dwarf::DW_OP_const2s:
188 case dwarf::DW_OP_const4s:
189 case dwarf::DW_OP_const8s:
190 if (NextIt == Expression.end() ||
191 !dwarf::isTlsAddressOp(NextIt->getCode()))
192 break;
193 [[fallthrough]];
194 case dwarf::DW_OP_addr: {
195 HasLocationAddress = true;
196 // Check relocation for the address.
197 if (std::optional<int64_t> RelocAdjustment =
199 *U, Op, AttrOffset + CurExprOffset,
200 AttrOffset + Op.getEndOffset(), Verbose))
201 return std::make_pair(HasLocationAddress, *RelocAdjustment);
202 } break;
203 case dwarf::DW_OP_constx:
204 case dwarf::DW_OP_addrx: {
205 HasLocationAddress = true;
206 if (std::optional<uint64_t> AddressOffset =
207 DIE.getDwarfUnit()->getIndexedAddressOffset(
208 Op.getRawOperand(0))) {
209 // Check relocation for the address.
210 if (std::optional<int64_t> RelocAdjustment =
212 *U, Op, *AddressOffset,
213 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
214 Verbose))
215 return std::make_pair(HasLocationAddress, *RelocAdjustment);
216 }
217 } break;
218 default: {
219 // Nothing to do.
220 } break;
221 }
222 CurExprOffset = Op.getEndOffset();
223 }
224
225 return std::make_pair(HasLocationAddress, std::nullopt);
226 }
227};
228
229} // namespace dwarf_linker
230} // end namespace llvm
231
232#endif // LLVM_DWARFLINKER_ADDRESSESMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AddressRangesMap class maps values to the address ranges.
A structured debug information entry.
Definition DIE.h:840
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:878
dwarf::Tag getTag() const
Definition DIE.h:876
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
This class represents an Operation in the Expression.
An iterator to go through the expression operations.
Class representing an expression and its matching format.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
AddressesMap represents information about valid addresses used by debug information.
virtual bool hasValidRelocs()=0
Checks that there are valid relocations in the .debug_info section.
virtual void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset, int64_t LinkedOffset, uint64_t StartOffset, uint64_t EndOffset)=0
Update and save relocation values to be serialized.
virtual void clear()=0
Erases all data.
virtual std::optional< uint64_t > getNextLinkedSymbolStart(uint64_t LinkedAddr)
Returns the linked address of the first symbol placed at or after LinkedAddr, if one is known.
virtual bool needToSaveValidRelocs()=0
Check if the linker needs to gather and save relocation info.
virtual std::optional< StringRef > getLibraryInstallName()=0
uint64_t constrainCodeRangeHighPC(uint64_t LowPC, uint64_t HighPC, int64_t Adjustment)
Constrains the end of the code range starting at LowPC, whose addresses shift by Adjustment in the ou...
virtual std::optional< SymbolRange > getSymbolRangeForAddress(uint64_t Addr)
Returns the symbol range [LowPC, HighPC) containing Addr, if known.
virtual bool applyValidRelocs(MutableArrayRef< char > Data, uint64_t BaseOffset, bool IsLittleEndian)=0
Apply the valid relocations to the buffer Data, taking into account that Data is at BaseOffset in the...
virtual std::optional< int64_t > getExprOpAddressRelocAdjustment(DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset, uint64_t EndOffset, bool Verbose)=0
Checks that the specified DWARF expression operand Op references live code section and returns the re...
virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset)=0
Update the valid relocations that used OriginalUnitOffset as the compile unit offset,...
std::pair< bool, std::optional< int64_t > > getVariableRelocAdjustment(const DWARFDie &DIE, bool Verbose)
This function checks whether variable has DWARF expression containing operation referencing live addr...
virtual std::optional< int64_t > getSubprogramRelocAdjustment(const DWARFDie &DIE, bool Verbose)=0
Checks that the specified subprogram DIE references the live code section and returns the relocation ...
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
bool isTlsAddressOp(uint8_t O)
Definition Dwarf.h:1179
This is an optimization pass for GlobalISel generic memory operations.
DWARFExpression::Operation Op
SymbolRange(uint64_t LowPC, uint64_t HighPC)