1 //===-- LVBinaryReader.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 // This file defines the LVBinaryReader class, which is used to describe a 10 // binary reader. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H 15 #define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H 16 17 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h" 18 #include "llvm/MC/MCAsmInfo.h" 19 #include "llvm/MC/MCContext.h" 20 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 21 #include "llvm/MC/MCInstPrinter.h" 22 #include "llvm/MC/MCInstrInfo.h" 23 #include "llvm/MC/MCObjectFileInfo.h" 24 #include "llvm/MC/MCRegisterInfo.h" 25 #include "llvm/MC/MCSubtargetInfo.h" 26 #include "llvm/MC/TargetRegistry.h" 27 #include "llvm/Object/COFF.h" 28 #include "llvm/Object/ObjectFile.h" 29 30 namespace llvm { 31 namespace logicalview { 32 33 constexpr bool UpdateHighAddress = false; 34 35 // Logical scope, Section address, Section index, IsComdat. 36 struct LVSymbolTableEntry final { 37 LVScope *Scope = nullptr; 38 LVAddress Address = 0; 39 LVSectionIndex SectionIndex = 0; 40 bool IsComdat = false; 41 LVSymbolTableEntry() = default; LVSymbolTableEntryfinal42 LVSymbolTableEntry(LVScope *Scope, LVAddress Address, 43 LVSectionIndex SectionIndex, bool IsComdat) 44 : Scope(Scope), Address(Address), SectionIndex(SectionIndex), 45 IsComdat(IsComdat) {} 46 }; 47 48 // Function names extracted from the object symbol table. 49 class LVSymbolTable final { 50 using LVSymbolNames = std::map<std::string, LVSymbolTableEntry, std::less<>>; 51 LVSymbolNames SymbolNames; 52 53 public: 54 LVSymbolTable() = default; 55 56 void add(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex = 0); 57 void add(StringRef Name, LVAddress Address, LVSectionIndex SectionIndex, 58 bool IsComdat); 59 LVSectionIndex update(LVScope *Function); 60 61 const LVSymbolTableEntry &getEntry(StringRef Name); 62 LVAddress getAddress(StringRef Name); 63 LVSectionIndex getIndex(StringRef Name); 64 bool getIsComdat(StringRef Name); 65 66 void print(raw_ostream &OS); 67 }; 68 69 class LVBinaryReader : public LVReader { 70 // Function names extracted from the object symbol table. 71 LVSymbolTable SymbolTable; 72 73 // It contains the LVLineDebug elements representing the inlined logical 74 // lines for the current compile unit, created by parsing the CodeView 75 // S_INLINESITE symbol annotation data. 76 using LVInlineeLine = std::map<LVScope *, std::unique_ptr<LVLines>>; 77 LVInlineeLine CUInlineeLines; 78 79 // Instruction lines for a logical scope. These instructions are fetched 80 // during its merge with the debug lines. 81 LVDoubleMap<LVSectionIndex, LVScope *, LVLines *> ScopeInstructions; 82 83 // Links the scope with its first assembler address line. 84 LVDoubleMap<LVSectionIndex, LVAddress, LVScope *> AssemblerMappings; 85 86 // Mapping from virtual address to section. 87 // The virtual address refers to the address where the section is loaded. 88 using LVSectionAddresses = std::map<LVSectionIndex, object::SectionRef>; 89 LVSectionAddresses SectionAddresses; 90 addSectionAddress(const object::SectionRef & Section)91 void addSectionAddress(const object::SectionRef &Section) { 92 if (SectionAddresses.find(Section.getAddress()) == SectionAddresses.end()) 93 SectionAddresses.emplace(Section.getAddress(), Section); 94 } 95 96 // Image base and virtual address for Executable file. 97 uint64_t ImageBaseAddress = 0; 98 uint64_t VirtualAddress = 0; 99 100 // Object sections with machine code. 101 using LVSections = std::map<LVSectionIndex, object::SectionRef>; 102 LVSections Sections; 103 104 std::vector<std::unique_ptr<LVLines>> DiscoveredLines; 105 106 protected: 107 // It contains the LVLineDebug elements representing the logical lines for 108 // the current compile unit, created by parsing the debug line section. 109 LVLines CULines; 110 111 std::unique_ptr<const MCRegisterInfo> MRI; 112 std::unique_ptr<const MCAsmInfo> MAI; 113 std::unique_ptr<const MCSubtargetInfo> STI; 114 std::unique_ptr<const MCInstrInfo> MII; 115 std::unique_ptr<const MCDisassembler> MD; 116 std::unique_ptr<MCContext> MC; 117 std::unique_ptr<MCInstPrinter> MIP; 118 119 // https://yurydelendik.github.io/webassembly-dwarf/ 120 // 2. Consuming and Generating DWARF for WebAssembly Code 121 // Note: Some DWARF constructs don't map one-to-one onto WebAssembly 122 // constructs. We strive to enumerate and resolve any ambiguities here. 123 // 124 // 2.1. Code Addresses 125 // Note: DWARF associates various bits of debug info 126 // with particular locations in the program via its code address (instruction 127 // pointer or PC). However, WebAssembly's linear memory address space does not 128 // contain WebAssembly instructions. 129 // 130 // Wherever a code address (see 2.17 of [DWARF]) is used in DWARF for 131 // WebAssembly, it must be the offset of an instruction relative within the 132 // Code section of the WebAssembly file. The DWARF is considered malformed if 133 // a PC offset is between instruction boundaries within the Code section. 134 // 135 // Note: It is expected that a DWARF consumer does not know how to decode 136 // WebAssembly instructions. The instruction pointer is selected as the offset 137 // in the binary file of the first byte of the instruction, and it is 138 // consistent with the WebAssembly Web API conventions definition of the code 139 // location. 140 // 141 // EXAMPLE: .DEBUG_LINE INSTRUCTION POINTERS 142 // The .debug_line DWARF section maps instruction pointers to source 143 // locations. With WebAssembly, the .debug_line section maps Code 144 // section-relative instruction offsets to source locations. 145 // 146 // EXAMPLE: DW_AT_* ATTRIBUTES 147 // For entities with a single associated code address, DWARF uses 148 // the DW_AT_low_pc attribute to specify the associated code address value. 149 // For WebAssembly, the DW_AT_low_pc's value is a Code section-relative 150 // instruction offset. 151 // 152 // For entities with a single contiguous range of code, DWARF uses a 153 // pair of DW_AT_low_pc and DW_AT_high_pc attributes to specify the associated 154 // contiguous range of code address values. For WebAssembly, these attributes 155 // are Code section-relative instruction offsets. 156 // 157 // For entities with multiple ranges of code, DWARF uses the DW_AT_ranges 158 // attribute, which refers to the array located at the .debug_ranges section. 159 LVAddress WasmCodeSectionOffset = 0; 160 161 // Loads all info for the architecture of the provided object file. 162 Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures); 163 mapRangeAddress(const object::ObjectFile & Obj)164 virtual void mapRangeAddress(const object::ObjectFile &Obj) {} mapRangeAddress(const object::ObjectFile & Obj,const object::SectionRef & Section,bool IsComdat)165 virtual void mapRangeAddress(const object::ObjectFile &Obj, 166 const object::SectionRef &Section, 167 bool IsComdat) {} 168 169 // Create a mapping from virtual address to section. 170 void mapVirtualAddress(const object::ObjectFile &Obj); 171 void mapVirtualAddress(const object::COFFObjectFile &COFFObj); 172 173 Expected<std::pair<LVSectionIndex, object::SectionRef>> 174 getSection(LVScope *Scope, LVAddress Address, LVSectionIndex SectionIndex); 175 176 void includeInlineeLines(LVSectionIndex SectionIndex, LVScope *Function); 177 178 Error createInstructions(); 179 Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex); 180 Error createInstructions(LVScope *Function, LVSectionIndex SectionIndex, 181 const LVNameInfo &NameInfo); 182 183 void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex); 184 void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex, 185 LVScope *Function); 186 187 public: 188 LVBinaryReader() = delete; LVBinaryReader(StringRef Filename,StringRef FileFormatName,ScopedPrinter & W,LVBinaryType BinaryType)189 LVBinaryReader(StringRef Filename, StringRef FileFormatName, ScopedPrinter &W, 190 LVBinaryType BinaryType) 191 : LVReader(Filename, FileFormatName, W, BinaryType) {} 192 LVBinaryReader(const LVBinaryReader &) = delete; 193 LVBinaryReader &operator=(const LVBinaryReader &) = delete; 194 virtual ~LVBinaryReader() = default; 195 addInlineeLines(LVScope * Scope,LVLines & Lines)196 void addInlineeLines(LVScope *Scope, LVLines &Lines) { 197 CUInlineeLines.emplace(Scope, std::make_unique<LVLines>(std::move(Lines))); 198 } 199 200 // Convert Segment::Offset pair to absolute address. 201 LVAddress linearAddress(uint16_t Segment, uint32_t Offset, 202 LVAddress Addendum = 0) { 203 return ImageBaseAddress + (Segment * VirtualAddress) + Offset + Addendum; 204 } 205 206 void addToSymbolTable(StringRef Name, LVScope *Function, 207 LVSectionIndex SectionIndex = 0); 208 void addToSymbolTable(StringRef Name, LVAddress Address, 209 LVSectionIndex SectionIndex, bool IsComdat); 210 LVSectionIndex updateSymbolTable(LVScope *Function); 211 212 const LVSymbolTableEntry &getSymbolTableEntry(StringRef Name); 213 LVAddress getSymbolTableAddress(StringRef Name); 214 LVSectionIndex getSymbolTableIndex(StringRef Name); 215 bool getSymbolTableIsComdat(StringRef Name); 216 getSectionIndex(LVScope * Scope)217 LVSectionIndex getSectionIndex(LVScope *Scope) override { 218 return Scope ? getSymbolTableIndex(Scope->getLinkageName()) 219 : DotTextSectionIndex; 220 } 221 222 void print(raw_ostream &OS) const; 223 224 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()225 void dump() const { print(dbgs()); } 226 #endif 227 }; 228 229 } // end namespace logicalview 230 } // end namespace llvm 231 232 #endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVBINARYREADER_H 233