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 /// Returns the relocation adjustment value for the .debug_addr entry that the
49 /// DW_OP_addrx or DW_OP_constx operation \p Op refers to, or std::nullopt if
50 /// there is no corresponding live address. The entry may name a different
51 /// symbol than whatever owns the expression, such as a variable in a location
52 /// list covering a function's code, and that symbol may have moved by a
53 /// different amount.
54 std::optional<int64_t> getAddrIndexRelocAdjustment(
56 std::optional<uint64_t> AddrOffset =
57 U.getIndexedAddressOffset(Op.getRawOperand(0));
58 if (!AddrOffset)
59 return std::nullopt;
61 U, Op, *AddrOffset, *AddrOffset + U.getAddressByteSize(), Verbose);
62 }
63
64 /// Checks that the specified subprogram \p DIE references the live code
65 /// section and returns the relocation adjustment value (to get the linked
66 /// address this value might be added to the source subprogram address).
67 /// Allowed kinds of input DIE: DW_TAG_subprogram, DW_TAG_label.
68 /// Print debug output if \p Verbose is true.
69 /// \returns relocation adjustment value or std::nullopt if there is no
70 /// corresponding live address.
71 virtual std::optional<int64_t>
73
74 // Returns the library install name associated to the AddessesMap.
75 virtual std::optional<StringRef> getLibraryInstallName() = 0;
76
77 /// Apply the valid relocations to the buffer \p Data, taking into
78 /// account that Data is at \p BaseOffset in the .debug_info section.
79 ///
80 /// \returns true whether any reloc has been applied.
82 bool IsLittleEndian) = 0;
83
84 /// Check if the linker needs to gather and save relocation info.
85 virtual bool needToSaveValidRelocs() = 0;
86
87 /// Update and save relocation values to be serialized
88 virtual void updateAndSaveValidRelocs(bool IsDWARF5,
89 uint64_t OriginalUnitOffset,
90 int64_t LinkedOffset,
91 uint64_t StartOffset,
92 uint64_t EndOffset) = 0;
93
94 /// Update the valid relocations that used OriginalUnitOffset as the compile
95 /// unit offset, and update their values to reflect OutputUnitOffset.
96 virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
97 uint64_t OutputUnitOffset) = 0;
98
99 /// Erases all data.
100 virtual void clear() = 0;
101
102 /// The extent the linker gave a symbol, in source address space.
109
110 /// Returns the symbol range [LowPC, HighPC) containing \p Addr, if known.
111 virtual std::optional<SymbolRange> getSymbolRangeForAddress(uint64_t Addr) {
112 return std::nullopt;
113 }
114
115 /// Returns the linked address of the first symbol placed at or after
116 /// \p LinkedAddr, if one is known.
117 virtual std::optional<uint64_t>
119 return std::nullopt;
120 }
121
122 /// Constrains the end of the code range starting at \p LowPC, whose addresses
123 /// shift by \p Adjustment in the output. \p HighPC is an address, not a
124 /// length.
125 ///
126 /// The linker places symbols independently, so a range overrunning the symbol
127 /// it starts in can cover a different one once linked. Only that overlap is
128 /// repaired.
130 int64_t Adjustment) {
131 std::optional<SymbolRange> Symbol = getSymbolRangeForAddress(LowPC);
132 if (!Symbol)
133 return HighPC;
134 assert(Symbol->LowPC <= LowPC && LowPC < Symbol->HighPC &&
135 "Symbol range must contain the address it was looked up for");
136 uint64_t LinkedSymbolHighPC = Symbol->HighPC + Adjustment;
137 assert(LinkedSymbolHighPC > Symbol->LowPC + Adjustment &&
138 "Adjusting a symbol range must preserve its order");
139 std::optional<uint64_t> NextStart =
140 getNextLinkedSymbolStart(LinkedSymbolHighPC);
141 if (!NextStart)
142 return HighPC;
143 assert(*NextStart >= LinkedSymbolHighPC &&
144 "A range must never be cut short of its own symbol");
145 return std::min(HighPC, *NextStart - Adjustment);
146 }
147
148 /// This function checks whether variable has DWARF expression containing
149 /// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
150 /// \returns first is true if the expression has an operation referencing an
151 /// address.
152 /// second is the relocation adjustment value if the live address is
153 /// referenced.
154 std::pair<bool, std::optional<int64_t>>
156 assert((DIE.getTag() == dwarf::DW_TAG_variable ||
157 DIE.getTag() == dwarf::DW_TAG_constant) &&
158 "Wrong type of input die");
159
160 const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
161
162 // Check if DIE has DW_AT_location attribute.
163 DWARFUnit *U = DIE.getDwarfUnit();
164 std::optional<uint32_t> LocationIdx =
165 Abbrev->findAttributeIndex(dwarf::DW_AT_location);
166 if (!LocationIdx)
167 return std::make_pair(false, std::nullopt);
168
169 // Get offset to the DW_AT_location attribute.
170 uint64_t AttrOffset =
171 Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
172
173 // Get value of the DW_AT_location attribute.
174 std::optional<DWARFFormValue> LocationValue =
175 Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
176 if (!LocationValue)
177 return std::make_pair(false, std::nullopt);
178
179 // Check that DW_AT_location attribute is of 'exprloc' class.
180 // Handling value of location expressions for attributes of 'loclist'
181 // class is not implemented yet.
182 std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
183 if (!Expr)
184 return std::make_pair(false, std::nullopt);
185
186 // Parse 'exprloc' expression.
187 DataExtractor Data(*Expr, U->getContext().isLittleEndian());
188 DWARFExpression Expression(Data, U->getAddressByteSize(),
189 U->getFormParams().Format);
190
191 bool HasLocationAddress = false;
192 uint64_t CurExprOffset = 0;
193 for (DWARFExpression::iterator It = Expression.begin();
194 It != Expression.end(); ++It) {
195 DWARFExpression::iterator NextIt = It;
196 ++NextIt;
197
198 const DWARFExpression::Operation &Op = *It;
199 switch (Op.getCode()) {
200 case dwarf::DW_OP_const2u:
201 case dwarf::DW_OP_const4u:
202 case dwarf::DW_OP_const8u:
203 case dwarf::DW_OP_const2s:
204 case dwarf::DW_OP_const4s:
205 case dwarf::DW_OP_const8s:
206 if (NextIt == Expression.end() ||
207 !dwarf::isTlsAddressOp(NextIt->getCode()))
208 break;
209 [[fallthrough]];
210 case dwarf::DW_OP_addr: {
211 HasLocationAddress = true;
212 // Check relocation for the address.
213 if (std::optional<int64_t> RelocAdjustment =
215 *U, Op, AttrOffset + CurExprOffset,
216 AttrOffset + Op.getEndOffset(), Verbose))
217 return std::make_pair(HasLocationAddress, *RelocAdjustment);
218 } break;
219 case dwarf::DW_OP_constx:
220 case dwarf::DW_OP_addrx: {
221 HasLocationAddress = true;
222 if (std::optional<uint64_t> AddressOffset =
223 DIE.getDwarfUnit()->getIndexedAddressOffset(
224 Op.getRawOperand(0))) {
225 // Check relocation for the address.
226 if (std::optional<int64_t> RelocAdjustment =
228 *U, Op, *AddressOffset,
229 *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
230 Verbose))
231 return std::make_pair(HasLocationAddress, *RelocAdjustment);
232 }
233 } break;
234 default: {
235 // Nothing to do.
236 } break;
237 }
238 CurExprOffset = Op.getEndOffset();
239 }
240
241 return std::make_pair(HasLocationAddress, std::nullopt);
242 }
243};
244
245} // namespace dwarf_linker
246} // end namespace llvm
247
248#endif // LLVM_DWARFLINKER_ADDRESSESMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
AddressRangesMap class maps values to the address ranges.
A structured debug information entry.
Definition DIE.h:835
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:870
dwarf::Tag getTag() const
Definition DIE.h:868
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
std::optional< int64_t > getAddrIndexRelocAdjustment(DWARFUnit &U, const DWARFExpression::Operation &Op, bool Verbose)
Returns the relocation adjustment value for the .debug_addr entry that the DW_OP_addrx or DW_OP_const...
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:1196
This is an optimization pass for GlobalISel generic memory operations.
DWARFExpression::Operation Op
SymbolRange(uint64_t LowPC, uint64_t HighPC)