|
|
|||
File indexing completed on 2026-05-10 08:43:42
0001 //===- LineTable.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_DEBUGINFO_GSYM_LINETABLE_H 0010 #define LLVM_DEBUGINFO_GSYM_LINETABLE_H 0011 0012 #include "llvm/DebugInfo/GSYM/LineEntry.h" 0013 #include "llvm/Support/Error.h" 0014 #include <cstdint> 0015 #include <vector> 0016 0017 namespace llvm { 0018 namespace gsym { 0019 0020 struct FunctionInfo; 0021 class FileWriter; 0022 0023 /// LineTable class contains deserialized versions of line tables for each 0024 /// function's address ranges. 0025 /// 0026 /// When saved to disk, the line table is encoded using a modified version of 0027 /// the DWARF line tables that only tracks address to source file and line. 0028 /// 0029 /// ENCODING 0030 /// 0031 /// The line table starts with a small prolog that contains the following 0032 /// values: 0033 /// 0034 /// ENCODING NAME DESCRIPTION 0035 /// ======== =========== ==================================================== 0036 /// SLEB MinDelta The min line delta for special opcodes that advance 0037 /// the address and line number. 0038 /// SLEB MaxDelta The max line delta for single byte opcodes that 0039 /// advance the address and line number. 0040 /// ULEB FirstLine The value of the first source line number to 0041 /// initialize the LineEntry with. 0042 /// 0043 /// Once these prolog items are read, we initialize a LineEntry struct with 0044 /// the start address of the function from the FunctionInfo's address range, 0045 /// a default file index of 1, and the line number set to "FirstLine" from 0046 /// the prolog above: 0047 /// 0048 /// LineEntry Row(BaseAddr, 1, FirstLine); 0049 /// 0050 /// The line table state machine is now initialized and ready to be parsed. 0051 /// The stream that follows this encodes the line entries in a compact 0052 /// form. Some opcodes cause "Row" to be modified and some opcodes may also 0053 /// push "Row" onto the end of the "LineTable.Lines" vector. The end result 0054 /// is a vector of LineEntry structs that is sorted in ascending address 0055 /// order. 0056 /// 0057 /// NORMAL OPCODES 0058 /// 0059 /// The opcodes 0 through 3 are normal in opcodes. Their encoding and 0060 /// descriptions are listed below: 0061 /// 0062 /// ENCODING ENUMERATION VALUE DESCRIPTION 0063 /// ======== ================ ===== ======================================== 0064 /// LTOC_EndSequence 0x00 Parsing is done. 0065 /// ULEB LTOC_SetFile 0x01 Row.File = ULEB 0066 /// ULEB LTOC_AdvancePC 0x02 Row.Addr += ULEB, push "Row". 0067 /// SLEB LTOC_AdvanceLine 0x03 Row.Line += SLEB 0068 /// LTOC_FirstSpecial 0x04 First special opcode (see SPECIAL 0069 /// OPCODES below). 0070 /// 0071 /// SPECIAL OPCODES 0072 /// 0073 /// Opcodes LTOC_FirstSpecial through 255 are special opcodes that always 0074 /// increment both the Row.Addr and Row.Line and push "Row" onto the 0075 /// LineEntry.Lines array. They do this by using some of the bits to 0076 /// increment/decrement the source line number, and some of the bits to 0077 /// increment the address. Line numbers can go up or down when making line 0078 /// tables, where addresses always only increase since line tables are sorted 0079 /// by address. 0080 /// 0081 /// In order to calculate the amount to increment the line and address for 0082 /// these special opcodes, we calculate the number of values reserved for the 0083 /// line increment/decrement using the "MinDelta" and "MaxDelta" from the 0084 /// prolog: 0085 /// 0086 /// const int64_t LineRange = MaxDelta - MinDelta + 1; 0087 /// 0088 /// Then we can adjust the opcode to not include any of the normal opcodes: 0089 /// 0090 /// const uint8_t AdjustedOp = Opcode - LTOC_FirstSpecial; 0091 /// 0092 /// And we can calculate the line offset, and address offset: 0093 /// 0094 /// const int64_t LineDelta = MinDelta + (AdjustedOp % LineRange); 0095 /// const uint64_t AddrDelta = (AdjustedOp / LineRange); 0096 /// 0097 /// And use these to modify our "Row": 0098 /// 0099 /// Row.Line += LineDelta; 0100 /// Row.Addr += AddrDelta; 0101 /// 0102 /// And push a row onto the line table: 0103 /// 0104 /// Lines.push_back(Row); 0105 /// 0106 /// This is verify similar to the way that DWARF encodes its line tables. The 0107 /// only difference is the DWARF line tables have more normal opcodes and the 0108 /// "Row" contains more members, like source column number, bools for end of 0109 /// prologue, beginnging of epilogue, is statement and many others. There are 0110 /// also more complex rules that happen for the extra normal opcodes. By 0111 /// leaving these extra opcodes out, we leave more bits for the special 0112 /// opcodes that allows us to encode line tables in fewer bytes than standard 0113 /// DWARF encodings. 0114 /// 0115 /// Opcodes that will push "Row" onto the LineEntry.Lines include the 0116 /// LTOC_AdvancePC opcode and all special opcodes. All other opcodes 0117 /// only modify the current "Row", or cause the line table to end. 0118 class LineTable { 0119 typedef std::vector<gsym::LineEntry> Collection; 0120 Collection Lines; ///< All line entries in the line table. 0121 public: 0122 /// Lookup a single address within a line table's data. 0123 /// 0124 /// Clients have the option to decode an entire line table using 0125 /// LineTable::decode() or just find a single matching entry using this 0126 /// function. The benefit of using this function is that parsed LineEntry 0127 /// objects that do not match will not be stored in an array. This will avoid 0128 /// memory allocation costs and parsing can stop once a match has been found. 0129 /// 0130 /// \param Data The binary stream to read the data from. This object must 0131 /// have the data for the LineTable object starting at offset zero. The data 0132 /// can contain more data than needed. 0133 /// 0134 /// \param BaseAddr The base address to use when decoding the line table. 0135 /// This will be the FunctionInfo's start address and will be used to 0136 /// initialize the line table row prior to parsing any opcodes. 0137 /// 0138 /// \returns An LineEntry object if a match is found, error otherwise. 0139 static Expected<LineEntry> lookup(DataExtractor &Data, uint64_t BaseAddr, 0140 uint64_t Addr); 0141 0142 /// Decode an LineTable object from a binary data stream. 0143 /// 0144 /// \param Data The binary stream to read the data from. This object must 0145 /// have the data for the LineTable object starting at offset zero. The data 0146 /// can contain more data than needed. 0147 /// 0148 /// \param BaseAddr The base address to use when decoding the line table. 0149 /// This will be the FunctionInfo's start address and will be used to 0150 /// initialize the line table row prior to parsing any opcodes. 0151 /// 0152 /// \returns An LineTable or an error describing the issue that was 0153 /// encountered during decoding. 0154 static llvm::Expected<LineTable> decode(DataExtractor &Data, 0155 uint64_t BaseAddr); 0156 /// Encode this LineTable object into FileWriter stream. 0157 /// 0158 /// \param O The binary stream to write the data to at the current file 0159 /// position. 0160 /// 0161 /// \param BaseAddr The base address to use when decoding the line table. 0162 /// This will be the FunctionInfo's start address. 0163 /// 0164 /// \returns An error object that indicates success or failure or the 0165 /// encoding process. 0166 llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const; 0167 bool empty() const { return Lines.empty(); } 0168 void clear() { Lines.clear(); } 0169 /// Return the first line entry if the line table isn't empty. 0170 /// 0171 /// \returns An optional line entry with the first line entry if the line 0172 /// table isn't empty, or std::nullopt if the line table is emtpy. 0173 std::optional<LineEntry> first() const { 0174 if (Lines.empty()) 0175 return std::nullopt; 0176 return Lines.front(); 0177 } 0178 /// Return the last line entry if the line table isn't empty. 0179 /// 0180 /// \returns An optional line entry with the last line entry if the line 0181 /// table isn't empty, or std::nullopt if the line table is emtpy. 0182 std::optional<LineEntry> last() const { 0183 if (Lines.empty()) 0184 return std::nullopt; 0185 return Lines.back(); 0186 } 0187 void push(const LineEntry &LE) { 0188 Lines.push_back(LE); 0189 } 0190 size_t isValid() const { 0191 return !Lines.empty(); 0192 } 0193 size_t size() const { 0194 return Lines.size(); 0195 } 0196 LineEntry &get(size_t i) { 0197 assert(i < Lines.size()); 0198 return Lines[i]; 0199 } 0200 const LineEntry &get(size_t i) const { 0201 assert(i < Lines.size()); 0202 return Lines[i]; 0203 } 0204 LineEntry &operator[](size_t i) { 0205 return get(i); 0206 } 0207 const LineEntry &operator[](size_t i) const { 0208 return get(i); 0209 } 0210 bool operator==(const LineTable &RHS) const { 0211 return Lines == RHS.Lines; 0212 } 0213 bool operator!=(const LineTable &RHS) const { 0214 return Lines != RHS.Lines; 0215 } 0216 bool operator<(const LineTable &RHS) const { 0217 const auto LHSSize = Lines.size(); 0218 const auto RHSSize = RHS.Lines.size(); 0219 if (LHSSize == RHSSize) 0220 return Lines < RHS.Lines; 0221 return LHSSize < RHSSize; 0222 } 0223 Collection::const_iterator begin() const { return Lines.begin(); } 0224 Collection::const_iterator end() const { return Lines.end(); } 0225 0226 }; 0227 0228 raw_ostream &operator<<(raw_ostream &OS, const gsym::LineTable <); 0229 0230 } // namespace gsym 0231 } // namespace llvm 0232 0233 #endif // LLVM_DEBUGINFO_GSYM_LINETABLE_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|