35#include "llvm/ADT/Twine.h"
67 return std::string(llvm::formatv(
"{0}", checksum.
digest()));
72 : m_last_support_file_sp(std::make_shared<
SupportFile>()), m_last_line(0),
73 m_last_count(0), m_default_set(false), m_target_wp(target_sp),
74 m_debugger_wp(target_sp->GetDebugger().shared_from_this()) {}
77 : m_last_support_file_sp(std::make_shared<
SupportFile>()), m_last_line(0),
78 m_last_count(0), m_default_set(false), m_target_wp(),
79 m_debugger_wp(debugger_sp) {}
85 assert(support_file_sp &&
"SupportFileSP must be valid");
87 FileSpec file_spec = support_file_sp->GetSpecOnly();
96 if (!debugger_sp || !debugger_sp->GetUseSourceCache()) {
97 LLDB_LOG(log,
"Source file caching disabled: creating new source file: {0}",
100 return std::make_shared<File>(support_file_sp, target_sp);
101 return std::make_shared<File>(support_file_sp, debugger_sp);
110 process_sp->GetSourceFileCache().FindSourceFile(file_spec)) {
111 LLDB_LOG(log,
"Found source file in the process cache: {0}", file_spec);
112 if (file_sp->PathRemappingIsStale()) {
113 LLDB_LOG(log,
"Path remapping is stale: removing file from caches: {0}",
118 debugger_sp->GetSourceFileCache().RemoveSourceFile(file_sp);
119 process_sp->GetSourceFileCache().RemoveSourceFile(file_sp);
129 FileSP file_sp = debugger_sp->GetSourceFileCache().FindSourceFile(file_spec);
134 LLDB_LOG(log,
"Found source file in the debugger cache: {0}", file_spec);
137 if (file_sp && file_sp->PathRemappingIsStale()) {
138 LLDB_LOG(log,
"Path remapping is stale: {0}", file_spec);
143 if (file_sp && file_sp->ModificationTimeIsStale()) {
144 LLDB_LOG(log,
"Modification time is stale: {0}", file_spec);
150 file_sp->GetSupportFile()->GetSpecOnly())) {
151 LLDB_LOG(log,
"File doesn't exist on disk: {0}", file_spec);
158 LLDB_LOG(log,
"Creating and caching new source file: {0}", file_spec);
162 file_sp = std::make_shared<File>(support_file_sp, target_sp);
164 file_sp = std::make_shared<File>(support_file_sp, debugger_sp);
168 debugger_sp->GetSourceFileCache().AddSourceFile(file_spec, file_sp);
170 process_sp->GetSourceFileCache().AddSourceFile(file_spec, file_sp);
182 if (!debugger_sp->GetUseColor())
185 return debugger_sp->GetHighlightSource();
196 if (!debugger_sp->GetUseColor())
202 const auto value = debugger_sp->GetStopShowColumn();
215 const auto value = debugger_sp->GetStopShowColumn();
225 return debugger_sp && debugger_sp->GetUseColor();
229 uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
230 const char *current_line_cstr,
Stream *s,
237 if (start_line == 0) {
251 const uint32_t end_line = start_line + count - 1;
252 for (uint32_t line = start_line; line <= end_line; ++line) {
253 if (!last_file_sp->LineIsValid(line)) {
263 prefix = llvm::formatv(
"[{0}]", bp_count);
269 snprintf(buffer,
sizeof(buffer),
"%2.2s",
270 (line == curr_line) ? current_line_cstr :
"");
271 std::string current_line_highlight(buffer);
276 (debugger_sp->GetStopShowLineMarkerAnsiPrefix() +
277 current_line_highlight +
278 debugger_sp->GetStopShowLineMarkerAnsiSuffix())
282 s->
Printf(
"%s%s %-4u\t", prefix.c_str(), current_line_highlight.c_str(),
288 std::optional<size_t> columnToHighlight;
289 if (line == curr_line && column)
290 columnToHighlight = column - 1;
292 size_t this_line_size =
293 last_file_sp->DisplaySourceLines(line, columnToHighlight, 0, 0, s);
294 if (column != 0 && line == curr_line &&
297 std::string src_line;
298 last_file_sp->GetLine(line, src_line);
301 for (
size_t i = 0; i + 1 < column && i < src_line.length(); ++i)
302 s->
PutChar(src_line[i] ==
'\t' ?
'\t' :
' ');
306 if (this_line_size == 0) {
313 last_file_sp->GetSupportFile()->GetChecksum();
314 Checksum on_disk_checksum = last_file_sp->GetChecksum();
315 if (line_table_checksum && line_table_checksum != on_disk_checksum)
318 "{0}: source file checksum mismatch between line table "
319 "({1}) and file on disk ({2})",
320 last_file_sp->GetSupportFile()->GetSpecOnly().GetFilename(),
322 std::nullopt, &last_file_sp->GetChecksumWarningOnceFlag());
329 uint32_t context_before, uint32_t context_after,
330 const char *current_line_cstr,
Stream *s,
332 assert(support_file_sp &&
"SupportFile must be valid");
336 uint32_t count = context_before + context_after + 1;
337 if (line > context_before)
338 start_line = line - context_before;
343 if (last_file_sp.get() != file_sp.get()) {
350 start_line, count, line, column, current_line_cstr, s, bp_locs);
358 const bool have_default_file_line = last_file_sp &&
m_last_line > 0;
383 }
else if (have_default_file_line)
388 const uint32_t column = 0;
397 assert(support_file_sp &&
"SupportFile must be valid");
410std::optional<SourceManager::SupportFileAndLine>
423 Module *executable_ptr = target_sp->GetExecutableModulePointer();
424 if (executable_ptr) {
433 lldb::eFunctionNameTypeFull,
434 function_options, sc_list);
438 if (sc.function->GetAddressRange()
440 .CalculateSymbolContextLineEntry(line_entry)) {
457 std::vector<uint32_t> &match_lines) {
462 return file_sp->FindLinesMatchingRegex(regex, start_line, end_line,
468 : m_support_file_sp(std::make_shared<
SupportFile>()), m_checksum(),
469 m_mod_time(), m_debugger_wp(debugger_sp), m_target_wp(
TargetSP()) {
474 : m_support_file_sp(std::make_shared<
SupportFile>()), m_checksum(),
476 m_debugger_wp(target_sp ? target_sp->GetDebugger().shared_from_this()
485 SetSupportFile(support_file_sp);
489 m_source_map_mod_id = target_sp->GetSourcePathMap().GetModificationID();
492 if (m_mod_time == llvm::sys::TimePoint<>()) {
496 FileSpec file_spec = support_file_sp->GetSpecOnly();
498 bool check_inlines =
false;
501 target_sp->GetImages().ResolveSymbolContextForFilePath(
503 SymbolContextItem(eSymbolContextModule |
504 eSymbolContextCompUnit),
506 bool got_multiple =
false;
507 if (num_matches != 0) {
508 if (num_matches > 1) {
513 if (test_cu != sc.comp_unit)
517 test_cu = sc.comp_unit;
533 FileSpec file_spec = support_file_sp->GetSpecOnly();
538 auto remapped = target_sp->GetSourcePathMap().FindFile(file_spec);
541 if (target_sp->GetImages().FindSourceFile(file_spec, new_spec))
545 SetSupportFile(std::make_shared<SupportFile>(
546 *remapped, support_file_sp->GetChecksum()));
553 if (m_mod_time != llvm::sys::TimePoint<>()) {
555 m_support_file_sp->GetSpecOnly());
556 m_checksum = llvm::MD5::hash(m_data_sp->GetData());
561 FileSpec file_spec = support_file_sp->GetSpecOnly();
564 std::make_shared<SupportFile>(file_spec, support_file_sp->GetChecksum());
575 if (CalculateLineOffsets(line)) {
576 if (line < m_offsets.size())
577 return m_offsets[line - 1];
583 CalculateLineOffsets();
584 return m_offsets.size();
588 if (!LineIsValid(line))
591 size_t line_offset = GetLineOffset(line);
592 if (line_offset < m_data_sp->GetByteSize())
593 return (
const char *)m_data_sp->GetBytes() + line_offset;
598 bool include_newline_chars) {
599 if (!LineIsValid(line))
602 size_t start_offset = GetLineOffset(line);
603 size_t end_offset = GetLineOffset(line + 1);
605 end_offset = m_data_sp->GetByteSize();
607 if (end_offset > start_offset) {
608 uint32_t length = end_offset - start_offset;
609 if (!include_newline_chars) {
610 const char *line_start =
611 (
const char *)m_data_sp->GetBytes() + start_offset;
613 const char last_char = line_start[length - 1];
614 if ((last_char ==
'\r') || (last_char ==
'\n'))
629 if (CalculateLineOffsets(line))
630 return line < m_offsets.size();
639 m_support_file_sp->GetSpecOnly());
640 return curr_mod_time != llvm::sys::TimePoint<>() &&
641 m_mod_time != curr_mod_time;
646 return GetSourceMapModificationID() !=
647 target_sp->GetSourcePathMap().GetModificationID();
652 std::optional<size_t> column,
653 uint32_t context_before,
654 uint32_t context_after,
676 style.
selected.
Set(debugger_sp->GetStopShowColumnAnsiPrefix(),
677 debugger_sp->GetStopShowColumnAnsiSuffix());
681 GetSupportFile()->GetSpecOnly().GetPath(
false);
686 const uint32_t start_line =
687 line <= context_before ? 1 : line - context_before;
688 const uint32_t start_line_offset = GetLineOffset(start_line);
690 const uint32_t end_line = line + context_after;
691 uint32_t end_line_offset = GetLineOffset(end_line + 1);
693 end_line_offset = m_data_sp->GetByteSize();
695 assert(start_line_offset <= end_line_offset);
696 if (start_line_offset < end_line_offset) {
697 size_t count = end_line_offset - start_line_offset;
698 const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
700 auto ref = llvm::StringRef(
reinterpret_cast<const char *
>(cstr), count);
702 h.Highlight(style, ref, column,
"", *s);
714 std::vector<uint32_t> &match_lines) {
717 if (!LineIsValid(start_line) ||
718 (end_line !=
UINT32_MAX && !LineIsValid(end_line)))
720 if (start_line > end_line)
723 for (uint32_t line_no = start_line; line_no < end_line; line_no++) {
725 if (!GetLine(line_no, buffer))
728 match_lines.push_back(line_no);
746 if (!m_offsets.empty() && m_offsets[0] ==
UINT32_MAX)
749 if (m_offsets.empty()) {
750 if (m_data_sp.get() ==
nullptr)
753 const char *start = (
const char *)m_data_sp->GetBytes();
755 const char *end = start + m_data_sp->GetByteSize();
763 for (s = start; s < end; ++s) {
769 if (curr_ch != next_ch)
773 m_offsets.push_back(s + 1 - start);
776 if (!m_offsets.empty()) {
777 if (m_offsets.back() < size_t(end - start))
778 m_offsets.push_back(end - start);
784 assert(
"Not implemented yet" &&
false);
789 assert(
"Not implemented yet" &&
false);
795 if (!LineIsValid(line_no))
798 size_t start_offset = GetLineOffset(line_no);
799 size_t end_offset = GetLineOffset(line_no + 1);
801 end_offset = m_data_sp->GetByteSize();
803 buffer.assign((
const char *)m_data_sp->GetBytes() + start_offset,
804 end_offset - start_offset);
811 llvm::sys::ScopedWriter guard(m_mutex);
813 assert(file_sp &&
"invalid FileSP");
815 AddSourceFileImpl(file_spec, file_sp);
816 const FileSpec &resolved_file_spec = file_sp->GetSupportFile()->GetSpecOnly();
817 if (file_spec != resolved_file_spec)
818 AddSourceFileImpl(file_sp->GetSupportFile()->GetSpecOnly(), file_sp);
822 llvm::sys::ScopedWriter guard(m_mutex);
824 assert(file_sp &&
"invalid FileSP");
828 auto it = m_file_cache.begin();
829 while (it != m_file_cache.end()) {
830 if (it->second == file_sp)
831 it = m_file_cache.erase(it);
839 FileCache::iterator pos = m_file_cache.find(file_spec);
840 if (pos == m_file_cache.end()) {
841 m_file_cache[file_spec] = file_sp;
843 if (file_sp != pos->second)
844 m_file_cache[file_spec] = file_sp;
850 llvm::sys::ScopedReader guard(m_mutex);
852 FileCache::const_iterator pos = m_file_cache.find(file_spec);
853 if (pos != m_file_cache.end())
860 stream <<
"Modification time MD5 Checksum (on-disk) MD5 Checksum (line table) Lines Path\n";
861 stream <<
"------------------- -------------------------------- -------------------------------- -------- --------------------------------\n";
863 for (
auto &entry : m_file_cache) {
866 FileSP file = entry.second;
867 stream.
Format(
"{0:%Y-%m-%d %H:%M:%S} {1,32} {2,32} {3,8:d} {4}\n",
868 file->GetTimestamp(),
toString(file->GetChecksum()),
869 toString(file->GetSupportFile()->GetChecksum()),
870 file->GetNumLines(), entry.first.GetPath());
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static void resolve_tilde(FileSpec &file_spec)
static std::string toString(const Checksum &checksum)
static bool should_highlight_source(DebuggerSP debugger_sp)
static bool is_newline_char(char ch)
static bool should_show_stop_column_with_caret(DebuggerSP debugger_sp)
static bool should_show_stop_line_with_ansi(DebuggerSP debugger_sp)
static bool should_show_stop_column_with_ansi(DebuggerSP debugger_sp)
std::string digest() const
A class that describes a compilation unit.
lldb::SupportFileSP GetPrimarySupportFile() const
Return the primary source file associated with this compile unit.
Represents a generic declaration context in a program.
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const char * GetCString() const
Get the string value as a C string.
static void ReportWarning(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report warning events.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const ConstString & GetFilename() const
Filename string const get accessor.
const ConstString & GetDirectory() const
Directory string const get accessor.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
llvm::sys::TimePoint GetModificationTime(const FileSpec &file_spec) const
Returns the modification time of the given file.
static FileSystem & Instance()
std::shared_ptr< DataBuffer > CreateDataBuffer(const llvm::Twine &path, uint64_t size=0, uint64_t offset=0)
Create memory buffer from path.
void Set(llvm::StringRef prefix, llvm::StringRef suffix)
Sets the prefix and suffix strings.
Manages the available highlighters.
const Highlighter & getHighlighterFor(lldb::LanguageType language_type, llvm::StringRef path) const
Queries all known highlighter for one that can highlight some source code.
A class that describes an executable image and its associated object and symbol files.
void FindFunctions(const LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list)
Find functions by lookup info.
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
bool ModificationTimeIsStale() const
llvm::sys::TimePoint m_mod_time
void FindLinesMatchingRegex(RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector< uint32_t > &match_lines)
const char * PeekLineData(uint32_t line)
bool LineIsValid(uint32_t line)
bool PathRemappingIsStale() const
uint32_t GetLineLength(uint32_t line, bool include_newline_chars)
bool CalculateLineOffsets(uint32_t line=UINT32_MAX)
File(lldb::SupportFileSP support_file_sp, lldb::TargetSP target_sp)
lldb::SupportFileSP GetSupportFile() const
void CommonInitializer(lldb::SupportFileSP support_file_sp, lldb::TargetSP target_sp)
bool GetLine(uint32_t line_no, std::string &buffer)
uint32_t GetLineOffset(uint32_t line)
void SetSupportFile(lldb::SupportFileSP support_file_sp)
Set file and update modification time.
size_t DisplaySourceLines(uint32_t line, std::optional< size_t > column, uint32_t context_before, uint32_t context_after, Stream *s)
void AddSourceFileImpl(const FileSpec &file_spec, FileSP file_sp)
void RemoveSourceFile(const FileSP &file_sp)
FileSP FindSourceFile(const FileSpec &file_spec) const
void Dump(Stream &stream) const
void AddSourceFile(const FileSpec &file_spec, FileSP file_sp)
void FindLinesMatchingRegex(lldb::SupportFileSP support_file_sp, RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector< uint32_t > &match_lines)
bool SetDefaultFileAndLine(lldb::SupportFileSP support_file_sp, uint32_t line)
size_t DisplaySourceLinesWithLineNumbersUsingLastFile(uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column, const char *current_line_cstr, Stream *s, const SymbolContextList *bp_locs=nullptr)
std::shared_ptr< File > FileSP
std::optional< SupportFileAndLine > GetDefaultFileAndLine()
lldb::SupportFileSP m_last_support_file_sp
SourceManager(const lldb::DebuggerSP &debugger_sp)
A source manager can be made with a valid Target, in which case it can use the path remappings to fin...
lldb::DebuggerWP m_debugger_wp
lldb::TargetWP m_target_wp
FileSP GetFile(lldb::SupportFileSP support_file_sp)
size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse, const SymbolContextList *bp_locs=nullptr)
size_t DisplaySourceLinesWithLineNumbers(lldb::SupportFileSP support_file_sp, uint32_t line, uint32_t column, uint32_t context_before, uint32_t context_after, const char *current_line_cstr, Stream *s, const SymbolContextList *bp_locs=nullptr)
A stream class that can stream formatted output to a file.
void Format(const char *format, Args &&... args)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t EOL()
Output and End of Line character to the stream.
size_t GetWrittenBytes() const
Wraps a FileSpec and an optional Checksum.
Defines a list of symbol context objects.
bool GetContextAtIndex(size_t idx, SymbolContext &sc) const
Get accessor for a symbol context at index idx.
uint32_t NumLineEntriesWithLine(uint32_t line) const
Defines a symbol context baton that can be handed other debug core functions.
CompileUnit * comp_unit
The CompileUnit for a given query.
std::string FormatAnsiTerminalCodes(llvm::StringRef format, bool do_color=true)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
bool operator==(const Address &lhs, const Address &rhs)
const char * toString(AppleArm64ExceptionClass EC)
std::shared_ptr< lldb_private::SupportFile > SupportFileSP
@ eLanguageTypeUnknown
Unknown or invalid language value.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Debugger > DebuggerSP
@ eStopShowColumnAnsiOrCaret
std::shared_ptr< lldb_private::Target > TargetSP
Represents style that the highlighter should apply to the given source code.
static HighlightStyle MakeVimStyle()
Returns a HighlightStyle that is based on vim's default highlight style.
ColorStyle selected
The style for the token which is below the cursor of the user.
A line table entry class.
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
lldb::SupportFileSP file_sp
The source file, possibly mapped by the target.source-map setting.
Options used by Module::FindFunctions.
bool include_inlines
Include inlined functions.
bool include_symbols
Include the symbol table.