Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===-- LVBinaryReader.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 // This file defines the LVBinaryReader class, which is used to describe a
0010 // binary reader.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H
0015 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H
0016 
0017 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
0018 #include "llvm/MC/MCAsmInfo.h"
0019 #include "llvm/MC/MCContext.h"
0020 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
0021 #include "llvm/MC/MCInstPrinter.h"
0022 #include "llvm/MC/MCInstrInfo.h"
0023 #include "llvm/MC/MCObjectFileInfo.h"
0024 #include "llvm/MC/MCRegisterInfo.h"
0025 #include "llvm/MC/MCSubtargetInfo.h"
0026 #include "llvm/MC/TargetRegistry.h"
0027 #include "llvm/Object/COFF.h"
0028 #include "llvm/Object/ObjectFile.h"
0029 
0030 namespace llvm {
0031 namespace logicalview {
0032 
0033 constexpr bool UpdateHighAddress = false;
0034 
0035 // Logical scope, Section address, Section index, IsComdat.
0036 struct LVSymbolTableEntry final {
0037   LVScope *Scope = nullptr;
0038   LVAddress Address = 0;
0039   LVSectionIndex SectionIndex = 0;
0040   bool IsComdat = false;
0041   LVSymbolTableEntry() = default;
0042   LVSymbolTableEntry(LVScope *Scope, LVAddress Address,
0043                      LVSectionIndex SectionIndex, bool IsComdat)
0044       : Scope(Scope), Address(Address), SectionIndex(SectionIndex),
0045         IsComdat(IsComdat) {}
0046 };
0047 
0048 // Function names extracted from the object symbol table.
0049 class LVSymbolTable final {
0050   using LVSymbolNames = std::map<std::string, LVSymbolTableEntry, std::less<>>;
0051   LVSymbolNames SymbolNames;
0052 
0053 public:
0054   LVSymbolTable() = default;
0055 
0056   void add(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex = 0);
0057   void add(StringRef Name, LVAddress Address, LVSectionIndex SectionIndex,
0058            bool IsComdat);
0059   LVSectionIndex update(LVScope *Function);
0060 
0061   const LVSymbolTableEntry &getEntry(StringRef Name);
0062   LVAddress getAddress(StringRef Name);
0063   LVSectionIndex getIndex(StringRef Name);
0064   bool getIsComdat(StringRef Name);
0065 
0066   void print(raw_ostream &OS);
0067 };
0068 
0069 class LVBinaryReader : public LVReader {
0070   // Function names extracted from the object symbol table.
0071   LVSymbolTable SymbolTable;
0072 
0073   // It contains the LVLineDebug elements representing the inlined logical
0074   // lines for the current compile unit, created by parsing the CodeView
0075   // S_INLINESITE symbol annotation data.
0076   using LVInlineeLine = std::map<LVScope *, std::unique_ptr<LVLines>>;
0077   LVInlineeLine CUInlineeLines;
0078 
0079   // Instruction lines for a logical scope. These instructions are fetched
0080   // during its merge with the debug lines.
0081   LVDoubleMap<LVSectionIndex, LVScope *, LVLines *> ScopeInstructions;
0082 
0083   // Links the scope with its first assembler address line.
0084   LVDoubleMap<LVSectionIndex, LVAddress, LVScope *> AssemblerMappings;
0085 
0086   // Mapping from virtual address to section.
0087   // The virtual address refers to the address where the section is loaded.
0088   using LVSectionAddresses = std::map<LVSectionIndex, object::SectionRef>;
0089   LVSectionAddresses SectionAddresses;
0090 
0091   void addSectionAddress(const object::SectionRef &Section) {
0092     if (SectionAddresses.find(Section.getAddress()) == SectionAddresses.end())
0093       SectionAddresses.emplace(Section.getAddress(), Section);
0094   }
0095 
0096   // Scopes with ranges for current compile unit. It is used to find a line
0097   // giving its exact or closest address. To support comdat functions, all
0098   // addresses for the same section are recorded in the same map.
0099   using LVSectionRanges = std::map<LVSectionIndex, std::unique_ptr<LVRange>>;
0100   LVSectionRanges SectionRanges;
0101 
0102   // Image base and virtual address for Executable file.
0103   uint64_t ImageBaseAddress = 0;
0104   uint64_t VirtualAddress = 0;
0105 
0106   // Object sections with machine code.
0107   using LVSections = std::map<LVSectionIndex, object::SectionRef>;
0108   LVSections Sections;
0109 
0110   std::vector<std::unique_ptr<LVLines>> DiscoveredLines;
0111 
0112 protected:
0113   // It contains the LVLineDebug elements representing the logical lines for
0114   // the current compile unit, created by parsing the debug line section.
0115   LVLines CULines;
0116 
0117   std::unique_ptr<const MCRegisterInfo> MRI;
0118   std::unique_ptr<const MCAsmInfo> MAI;
0119   std::unique_ptr<const MCSubtargetInfo> STI;
0120   std::unique_ptr<const MCInstrInfo> MII;
0121   std::unique_ptr<const MCDisassembler> MD;
0122   std::unique_ptr<MCContext> MC;
0123   std::unique_ptr<MCInstPrinter> MIP;
0124 
0125   // https://yurydelendik.github.io/webassembly-dwarf/
0126   // 2. Consuming and Generating DWARF for WebAssembly Code
0127   // Note: Some DWARF constructs don't map one-to-one onto WebAssembly
0128   // constructs. We strive to enumerate and resolve any ambiguities here.
0129   //
0130   // 2.1. Code Addresses
0131   // Note: DWARF associates various bits of debug info
0132   // with particular locations in the program via its code address (instruction
0133   // pointer or PC). However, WebAssembly's linear memory address space does not
0134   // contain WebAssembly instructions.
0135   //
0136   // Wherever a code address (see 2.17 of [DWARF]) is used in DWARF for
0137   // WebAssembly, it must be the offset of an instruction relative within the
0138   // Code section of the WebAssembly file. The DWARF is considered malformed if
0139   // a PC offset is between instruction boundaries within the Code section.
0140   //
0141   // Note: It is expected that a DWARF consumer does not know how to decode
0142   // WebAssembly instructions. The instruction pointer is selected as the offset
0143   // in the binary file of the first byte of the instruction, and it is
0144   // consistent with the WebAssembly Web API conventions definition of the code
0145   // location.
0146   //
0147   // EXAMPLE: .DEBUG_LINE INSTRUCTION POINTERS
0148   // The .debug_line DWARF section maps instruction pointers to source
0149   // locations. With WebAssembly, the .debug_line section maps Code
0150   // section-relative instruction offsets to source locations.
0151   //
0152   // EXAMPLE: DW_AT_* ATTRIBUTES
0153   // For entities with a single associated code address, DWARF uses
0154   // the DW_AT_low_pc attribute to specify the associated code address value.
0155   // For WebAssembly, the DW_AT_low_pc's value is a Code section-relative
0156   // instruction offset.
0157   //
0158   // For entities with a single contiguous range of code, DWARF uses a
0159   // pair of DW_AT_low_pc and DW_AT_high_pc attributes to specify the associated
0160   // contiguous range of code address values. For WebAssembly, these attributes
0161   // are Code section-relative instruction offsets.
0162   //
0163   // For entities with multiple ranges of code, DWARF uses the DW_AT_ranges
0164   // attribute, which refers to the array located at the .debug_ranges section.
0165   LVAddress WasmCodeSectionOffset = 0;
0166 
0167   // Loads all info for the architecture of the provided object file.
0168   Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures);
0169 
0170   virtual void mapRangeAddress(const object::ObjectFile &Obj) {}
0171   virtual void mapRangeAddress(const object::ObjectFile &Obj,
0172                                const object::SectionRef &Section,
0173                                bool IsComdat) {}
0174 
0175   // Create a mapping from virtual address to section.
0176   void mapVirtualAddress(const object::ObjectFile &Obj);
0177   void mapVirtualAddress(const object::COFFObjectFile &COFFObj);
0178 
0179   Expected<std::pair<LVSectionIndex, object::SectionRef>>
0180   getSection(LVScope *Scope, LVAddress Address, LVSectionIndex SectionIndex);
0181 
0182   void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope);
0183   void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope,
0184                        LVAddress LowerAddress, LVAddress UpperAddress);
0185   LVRange *getSectionRanges(LVSectionIndex SectionIndex);
0186 
0187   void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function);
0188 
0189   Error createInstructions();
0190   Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex);
0191   Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex,
0192                            const LVNameInfo &NameInfo);
0193 
0194   void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex);
0195   void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex,
0196                     LVScope *Function);
0197 
0198 public:
0199   LVBinaryReader() = delete;
0200   LVBinaryReader(StringRef Filename, StringRef FileFormatName, ScopedPrinter &W,
0201                  LVBinaryType BinaryType)
0202       : LVReader(Filename, FileFormatName, W, BinaryType) {}
0203   LVBinaryReader(const LVBinaryReader &) = delete;
0204   LVBinaryReader &operator=(const LVBinaryReader &) = delete;
0205   virtual ~LVBinaryReader() = default;
0206 
0207   void addInlineeLines(LVScope *Scope, LVLines &Lines) {
0208     CUInlineeLines.emplace(Scope, std::make_unique<LVLines>(std::move(Lines)));
0209   }
0210 
0211   // Convert Segment::Offset pair to absolute address.
0212   LVAddress linearAddress(uint16_t Segment, uint32_t Offset,
0213                           LVAddress Addendum = 0) {
0214     return ImageBaseAddress + (Segment * VirtualAddress) + Offset + Addendum;
0215   }
0216 
0217   void addToSymbolTable(StringRef Name, LVScope *Function,
0218                         LVSectionIndex SectionIndex = 0);
0219   void addToSymbolTable(StringRef Name, LVAddress Address,
0220                         LVSectionIndex SectionIndex, bool IsComdat);
0221   LVSectionIndex updateSymbolTable(LVScope *Function);
0222 
0223   const LVSymbolTableEntry &getSymbolTableEntry(StringRef Name);
0224   LVAddress getSymbolTableAddress(StringRef Name);
0225   LVSectionIndex getSymbolTableIndex(StringRef Name);
0226   bool getSymbolTableIsComdat(StringRef Name);
0227 
0228   LVSectionIndex getSectionIndex(LVScope *Scope) override {
0229     return Scope ? getSymbolTableIndex(Scope->getLinkageName())
0230                  : DotTextSectionIndex;
0231   }
0232 
0233   void print(raw_ostream &OS) const;
0234 
0235 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0236   void dump() const { print(dbgs()); }
0237 #endif
0238 };
0239 
0240 } // end namespace logicalview
0241 } // end namespace llvm
0242 
0243 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H