File indexing completed on 2026-05-10 08:42:51
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_SYMBOL_LINETABLE_H
0010 #define LLDB_SYMBOL_LINETABLE_H
0011
0012 #include "lldb/Core/Address.h"
0013 #include "lldb/Core/ModuleChild.h"
0014 #include "lldb/Core/Section.h"
0015 #include "lldb/Core/SourceLocationSpec.h"
0016 #include "lldb/Symbol/LineEntry.h"
0017 #include "lldb/Utility/RangeMap.h"
0018 #include "lldb/lldb-private.h"
0019 #include <vector>
0020
0021 namespace lldb_private {
0022
0023
0024
0025 class LineSequence {
0026 public:
0027 LineSequence();
0028
0029 virtual ~LineSequence() = default;
0030
0031 virtual void Clear() = 0;
0032
0033 private:
0034 LineSequence(const LineSequence &) = delete;
0035 const LineSequence &operator=(const LineSequence &) = delete;
0036 };
0037
0038
0039
0040 class LineTable {
0041 public:
0042
0043
0044
0045
0046 LineTable(CompileUnit *comp_unit);
0047
0048
0049
0050
0051
0052 LineTable(CompileUnit *comp_unit,
0053 std::vector<std::unique_ptr<LineSequence>> &&sequences);
0054
0055
0056 ~LineTable();
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 void InsertLineEntry(lldb::addr_t file_addr, uint32_t line, uint16_t column,
0072 uint16_t file_idx, bool is_start_of_statement,
0073 bool is_start_of_basic_block, bool is_prologue_end,
0074 bool is_epilogue_begin, bool is_terminal_entry);
0075
0076
0077 static std::unique_ptr<LineSequence> CreateLineSequenceContainer();
0078
0079
0080
0081 static void AppendLineEntryToSequence(LineSequence *sequence, lldb::addr_t file_addr,
0082 uint32_t line, uint16_t column,
0083 uint16_t file_idx, bool is_start_of_statement,
0084 bool is_start_of_basic_block,
0085 bool is_prologue_end, bool is_epilogue_begin,
0086 bool is_terminal_entry);
0087
0088
0089 void InsertSequence(LineSequence *sequence);
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 void Dump(Stream *s, Target *target, Address::DumpStyle style,
0101 Address::DumpStyle fallback_style, bool show_line_ranges);
0102
0103 void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level);
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 bool FindLineEntryByAddress(const Address &so_addr, LineEntry &line_entry,
0123 uint32_t *index_ptr = nullptr);
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 uint32_t
0156 FindLineEntryIndexByFileIndex(uint32_t start_idx, uint32_t file_idx,
0157 const SourceLocationSpec &src_location_spec,
0158 LineEntry *line_entry_ptr);
0159
0160 uint32_t FindLineEntryIndexByFileIndex(
0161 uint32_t start_idx, const std::vector<uint32_t> &file_idx,
0162 const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr);
0163
0164 size_t FindLineEntriesForFileIndex(uint32_t file_idx, bool append,
0165 SymbolContextList &sc_list);
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 bool GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry);
0179
0180
0181
0182
0183
0184 uint32_t GetSize() const;
0185
0186 typedef lldb_private::RangeVector<lldb::addr_t, lldb::addr_t, 32>
0187 FileAddressRanges;
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 size_t GetContiguousFileAddressRanges(FileAddressRanges &file_ranges,
0202 bool append);
0203
0204 typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t>
0205 FileRangeMap;
0206
0207 LineTable *LinkLineTable(const FileRangeMap &file_range_map);
0208
0209 struct Entry {
0210 Entry()
0211 : line(0), is_start_of_statement(false), is_start_of_basic_block(false),
0212 is_prologue_end(false), is_epilogue_begin(false),
0213 is_terminal_entry(false) {}
0214
0215 Entry(lldb::addr_t _file_addr, uint32_t _line, uint16_t _column,
0216 uint16_t _file_idx, bool _is_start_of_statement,
0217 bool _is_start_of_basic_block, bool _is_prologue_end,
0218 bool _is_epilogue_begin, bool _is_terminal_entry)
0219 : file_addr(_file_addr), line(_line),
0220 is_start_of_statement(_is_start_of_statement),
0221 is_start_of_basic_block(_is_start_of_basic_block),
0222 is_prologue_end(_is_prologue_end),
0223 is_epilogue_begin(_is_epilogue_begin),
0224 is_terminal_entry(_is_terminal_entry), column(_column),
0225 file_idx(_file_idx) {}
0226
0227 int bsearch_compare(const void *key, const void *arrmem);
0228
0229 void Clear() {
0230 file_addr = LLDB_INVALID_ADDRESS;
0231 line = 0;
0232 column = 0;
0233 file_idx = 0;
0234 is_start_of_statement = false;
0235 is_start_of_basic_block = false;
0236 is_prologue_end = false;
0237 is_epilogue_begin = false;
0238 is_terminal_entry = false;
0239 }
0240
0241 static int Compare(const Entry &lhs, const Entry &rhs) {
0242
0243 #define SCALAR_COMPARE(a, b) \
0244 if (a < b) \
0245 return -1; \
0246 if (a > b) \
0247 return +1
0248 SCALAR_COMPARE(lhs.file_addr, rhs.file_addr);
0249 SCALAR_COMPARE(lhs.line, rhs.line);
0250 SCALAR_COMPARE(lhs.column, rhs.column);
0251 SCALAR_COMPARE(lhs.is_start_of_statement, rhs.is_start_of_statement);
0252 SCALAR_COMPARE(lhs.is_start_of_basic_block, rhs.is_start_of_basic_block);
0253
0254 SCALAR_COMPARE(rhs.is_prologue_end, lhs.is_prologue_end);
0255 SCALAR_COMPARE(lhs.is_epilogue_begin, rhs.is_epilogue_begin);
0256
0257 SCALAR_COMPARE(rhs.is_terminal_entry, lhs.is_terminal_entry);
0258 SCALAR_COMPARE(lhs.file_idx, rhs.file_idx);
0259 #undef SCALAR_COMPARE
0260 return 0;
0261 }
0262
0263 class LessThanBinaryPredicate {
0264 public:
0265 LessThanBinaryPredicate(LineTable *line_table);
0266 bool operator()(const LineTable::Entry &, const LineTable::Entry &) const;
0267 bool operator()(const std::unique_ptr<LineSequence> &,
0268 const std::unique_ptr<LineSequence> &) const;
0269
0270 protected:
0271 LineTable *m_line_table;
0272 };
0273
0274 static bool EntryAddressLessThan(const Entry &lhs, const Entry &rhs) {
0275 return lhs.file_addr < rhs.file_addr;
0276 }
0277
0278
0279
0280 lldb::addr_t file_addr = LLDB_INVALID_ADDRESS;
0281
0282
0283 uint32_t line : 27;
0284
0285 uint32_t is_start_of_statement : 1;
0286
0287 uint32_t is_start_of_basic_block : 1;
0288
0289
0290 uint32_t is_prologue_end : 1;
0291
0292
0293 uint32_t is_epilogue_begin : 1;
0294
0295
0296 uint32_t is_terminal_entry : 1;
0297
0298
0299 uint16_t column = 0;
0300
0301
0302 uint16_t file_idx = 0;
0303 };
0304
0305 protected:
0306 struct EntrySearchInfo {
0307 LineTable *line_table;
0308 lldb_private::Section *a_section;
0309 Entry *a_entry;
0310 };
0311
0312
0313 typedef std::vector<lldb_private::Section *>
0314 section_collection;
0315 typedef std::vector<Entry>
0316 entry_collection;
0317
0318 CompileUnit
0319 *m_comp_unit;
0320 entry_collection
0321 m_entries;
0322
0323
0324 class LineSequenceImpl : public LineSequence {
0325 public:
0326 LineSequenceImpl() = default;
0327
0328 ~LineSequenceImpl() override = default;
0329
0330 void Clear() override;
0331
0332 entry_collection
0333 m_entries;
0334 };
0335
0336 bool ConvertEntryAtIndexToLineEntry(uint32_t idx, LineEntry &line_entry);
0337
0338 private:
0339 LineTable(const LineTable &) = delete;
0340 const LineTable &operator=(const LineTable &) = delete;
0341
0342 template <typename T>
0343 uint32_t FindLineEntryIndexByFileIndexImpl(
0344 uint32_t start_idx, T file_idx,
0345 const SourceLocationSpec &src_location_spec, LineEntry *line_entry_ptr,
0346 std::function<bool(T, uint16_t)> file_idx_matcher) {
0347 const size_t count = m_entries.size();
0348 size_t best_match = UINT32_MAX;
0349
0350 if (!line_entry_ptr)
0351 return best_match;
0352
0353 const uint32_t line = src_location_spec.GetLine().value_or(0);
0354 const uint16_t column =
0355 src_location_spec.GetColumn().value_or(LLDB_INVALID_COLUMN_NUMBER);
0356 const bool exact_match = src_location_spec.GetExactMatch();
0357
0358 for (size_t idx = start_idx; idx < count; ++idx) {
0359
0360
0361 if (m_entries[idx].is_terminal_entry)
0362 continue;
0363
0364 if (!file_idx_matcher(file_idx, m_entries[idx].file_idx))
0365 continue;
0366
0367
0368
0369
0370
0371
0372 if (column == LLDB_INVALID_COLUMN_NUMBER) {
0373 if (m_entries[idx].line < line) {
0374 continue;
0375 } else if (m_entries[idx].line == line) {
0376 ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr);
0377 return idx;
0378 } else if (!exact_match) {
0379 if (best_match == UINT32_MAX ||
0380 m_entries[idx].line < m_entries[best_match].line)
0381 best_match = idx;
0382 }
0383 } else {
0384 if (m_entries[idx].line < line) {
0385 continue;
0386 } else if (m_entries[idx].line == line &&
0387 m_entries[idx].column == column) {
0388 ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr);
0389 return idx;
0390 } else if (!exact_match) {
0391 if (best_match == UINT32_MAX)
0392 best_match = idx;
0393 else if (m_entries[idx].line < m_entries[best_match].line)
0394 best_match = idx;
0395 else if (m_entries[idx].line == m_entries[best_match].line)
0396 if (m_entries[idx].column &&
0397 m_entries[idx].column < m_entries[best_match].column)
0398 best_match = idx;
0399 }
0400 }
0401 }
0402
0403 if (best_match != UINT32_MAX) {
0404 if (line_entry_ptr)
0405 ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr);
0406 return best_match;
0407 }
0408 return UINT32_MAX;
0409 }
0410 };
0411
0412 }
0413
0414 #endif