Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:49

0001 //===- AddressesMap.h -------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DWARFLINKER_ADDRESSESMAP_H
0010 #define LLVM_DWARFLINKER_ADDRESSESMAP_H
0011 
0012 #include "llvm/ADT/AddressRanges.h"
0013 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
0014 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
0015 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
0016 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
0017 #include <cstdint>
0018 
0019 namespace llvm {
0020 namespace dwarf_linker {
0021 
0022 /// Mapped value in the address map is the offset to apply to the
0023 /// linked address.
0024 using RangesTy = AddressRangesMap;
0025 
0026 /// AddressesMap represents information about valid addresses used
0027 /// by debug information. Valid addresses are those which points to
0028 /// live code sections. i.e. relocations for these addresses point
0029 /// into sections which would be/are placed into resulting binary.
0030 class AddressesMap {
0031 public:
0032   virtual ~AddressesMap() = default;
0033 
0034   /// Checks that there are valid relocations in the .debug_info
0035   /// section.
0036   virtual bool hasValidRelocs() = 0;
0037 
0038   /// Checks that the specified DWARF expression operand \p Op references live
0039   /// code section and returns the relocation adjustment value (to get the
0040   /// linked address this value might be added to the source expression operand
0041   /// address). Print debug output if \p Verbose is true.
0042   /// \returns relocation adjustment value or std::nullopt if there is no
0043   /// corresponding live address.
0044   virtual std::optional<int64_t> getExprOpAddressRelocAdjustment(
0045       DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
0046       uint64_t EndOffset, bool Verbose) = 0;
0047 
0048   /// Checks that the specified subprogram \p DIE references the live code
0049   /// section and returns the relocation adjustment value (to get the linked
0050   /// address this value might be added to the source subprogram address).
0051   /// Allowed kinds of input DIE: DW_TAG_subprogram, DW_TAG_label.
0052   /// Print debug output if \p Verbose is true.
0053   /// \returns relocation adjustment value or std::nullopt if there is no
0054   /// corresponding live address.
0055   virtual std::optional<int64_t>
0056   getSubprogramRelocAdjustment(const DWARFDie &DIE, bool Verbose) = 0;
0057 
0058   // Returns the library install name associated to the AddessesMap.
0059   virtual std::optional<StringRef> getLibraryInstallName() = 0;
0060 
0061   /// Apply the valid relocations to the buffer \p Data, taking into
0062   /// account that Data is at \p BaseOffset in the .debug_info section.
0063   ///
0064   /// \returns true whether any reloc has been applied.
0065   virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
0066                                 bool IsLittleEndian) = 0;
0067 
0068   /// Check if the linker needs to gather and save relocation info.
0069   virtual bool needToSaveValidRelocs() = 0;
0070 
0071   /// Update and save relocation values to be serialized
0072   virtual void updateAndSaveValidRelocs(bool IsDWARF5,
0073                                         uint64_t OriginalUnitOffset,
0074                                         int64_t LinkedOffset,
0075                                         uint64_t StartOffset,
0076                                         uint64_t EndOffset) = 0;
0077 
0078   /// Update the valid relocations that used OriginalUnitOffset as the compile
0079   /// unit offset, and update their values to reflect OutputUnitOffset.
0080   virtual void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
0081                                                uint64_t OutputUnitOffset) = 0;
0082 
0083   /// Erases all data.
0084   virtual void clear() = 0;
0085 
0086   /// This function checks whether variable has DWARF expression containing
0087   /// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
0088   /// \returns first is true if the expression has an operation referencing an
0089   /// address.
0090   ///          second is the relocation adjustment value if the live address is
0091   ///          referenced.
0092   std::pair<bool, std::optional<int64_t>>
0093   getVariableRelocAdjustment(const DWARFDie &DIE, bool Verbose) {
0094     assert((DIE.getTag() == dwarf::DW_TAG_variable ||
0095             DIE.getTag() == dwarf::DW_TAG_constant) &&
0096            "Wrong type of input die");
0097 
0098     const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
0099 
0100     // Check if DIE has DW_AT_location attribute.
0101     DWARFUnit *U = DIE.getDwarfUnit();
0102     std::optional<uint32_t> LocationIdx =
0103         Abbrev->findAttributeIndex(dwarf::DW_AT_location);
0104     if (!LocationIdx)
0105       return std::make_pair(false, std::nullopt);
0106 
0107     // Get offset to the DW_AT_location attribute.
0108     uint64_t AttrOffset =
0109         Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
0110 
0111     // Get value of the DW_AT_location attribute.
0112     std::optional<DWARFFormValue> LocationValue =
0113         Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
0114     if (!LocationValue)
0115       return std::make_pair(false, std::nullopt);
0116 
0117     // Check that DW_AT_location attribute is of 'exprloc' class.
0118     // Handling value of location expressions for attributes of 'loclist'
0119     // class is not implemented yet.
0120     std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
0121     if (!Expr)
0122       return std::make_pair(false, std::nullopt);
0123 
0124     // Parse 'exprloc' expression.
0125     DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
0126                        U->getAddressByteSize());
0127     DWARFExpression Expression(Data, U->getAddressByteSize(),
0128                                U->getFormParams().Format);
0129 
0130     bool HasLocationAddress = false;
0131     uint64_t CurExprOffset = 0;
0132     for (DWARFExpression::iterator It = Expression.begin();
0133          It != Expression.end(); ++It) {
0134       DWARFExpression::iterator NextIt = It;
0135       ++NextIt;
0136 
0137       const DWARFExpression::Operation &Op = *It;
0138       switch (Op.getCode()) {
0139       case dwarf::DW_OP_const2u:
0140       case dwarf::DW_OP_const4u:
0141       case dwarf::DW_OP_const8u:
0142       case dwarf::DW_OP_const2s:
0143       case dwarf::DW_OP_const4s:
0144       case dwarf::DW_OP_const8s:
0145         if (NextIt == Expression.end() || !isTlsAddressCode(NextIt->getCode()))
0146           break;
0147         [[fallthrough]];
0148       case dwarf::DW_OP_addr: {
0149         HasLocationAddress = true;
0150         // Check relocation for the address.
0151         if (std::optional<int64_t> RelocAdjustment =
0152                 getExprOpAddressRelocAdjustment(
0153                     *U, Op, AttrOffset + CurExprOffset,
0154                     AttrOffset + Op.getEndOffset(), Verbose))
0155           return std::make_pair(HasLocationAddress, *RelocAdjustment);
0156       } break;
0157       case dwarf::DW_OP_constx:
0158       case dwarf::DW_OP_addrx: {
0159         HasLocationAddress = true;
0160         if (std::optional<uint64_t> AddressOffset =
0161                 DIE.getDwarfUnit()->getIndexedAddressOffset(
0162                     Op.getRawOperand(0))) {
0163           // Check relocation for the address.
0164           if (std::optional<int64_t> RelocAdjustment =
0165                   getExprOpAddressRelocAdjustment(
0166                       *U, Op, *AddressOffset,
0167                       *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(),
0168                       Verbose))
0169             return std::make_pair(HasLocationAddress, *RelocAdjustment);
0170         }
0171       } break;
0172       default: {
0173         // Nothing to do.
0174       } break;
0175       }
0176       CurExprOffset = Op.getEndOffset();
0177     }
0178 
0179     return std::make_pair(HasLocationAddress, std::nullopt);
0180   }
0181 
0182 protected:
0183   inline bool isTlsAddressCode(uint8_t DW_OP_Code) {
0184     return DW_OP_Code == dwarf::DW_OP_form_tls_address ||
0185            DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
0186   }
0187 };
0188 
0189 } // namespace dwarf_linker
0190 } // end namespace llvm
0191 
0192 #endif // LLVM_DWARFLINKER_ADDRESSESMAP_H