35#include "llvm/ADT/Twine.h"
66 : m_last_line(0), m_last_count(0), m_default_set(false),
67 m_target_wp(target_sp),
68 m_debugger_wp(target_sp->GetDebugger().shared_from_this()) {}
71 : m_last_line(0), m_last_count(0), m_default_set(false), m_target_wp(),
72 m_debugger_wp(debugger_sp) {}
86 if (!debugger_sp || !debugger_sp->GetUseSourceCache()) {
87 LLDB_LOG(log,
"Source file caching disabled: creating new source file: {0}",
90 return std::make_shared<File>(file_spec, target_sp);
91 return std::make_shared<File>(file_spec, debugger_sp);
100 process_sp->GetSourceFileCache().FindSourceFile(file_spec)) {
101 LLDB_LOG(log,
"Found source file in the process cache: {0}", file_spec);
102 if (file_sp->PathRemappingIsStale()) {
103 LLDB_LOG(log,
"Path remapping is stale: removing file from caches: {0}",
108 debugger_sp->GetSourceFileCache().RemoveSourceFile(file_sp);
109 process_sp->GetSourceFileCache().RemoveSourceFile(file_sp);
119 FileSP file_sp = debugger_sp->GetSourceFileCache().FindSourceFile(file_spec);
124 LLDB_LOG(log,
"Found source file in the debugger cache: {0}", file_spec);
127 if (file_sp && file_sp->PathRemappingIsStale()) {
128 LLDB_LOG(log,
"Path remapping is stale: {0}", file_spec);
133 if (file_sp && file_sp->ModificationTimeIsStale()) {
134 LLDB_LOG(log,
"Modification time is stale: {0}", file_spec);
140 LLDB_LOG(log,
"File doesn't exist on disk: {0}", file_spec);
147 LLDB_LOG(log,
"Creating and caching new source file: {0}", file_spec);
151 file_sp = std::make_shared<File>(file_spec, target_sp);
153 file_sp = std::make_shared<File>(file_spec, debugger_sp);
157 debugger_sp->GetSourceFileCache().AddSourceFile(file_spec, file_sp);
159 process_sp->GetSourceFileCache().AddSourceFile(file_spec, file_sp);
171 if (!debugger_sp->GetUseColor())
174 return debugger_sp->GetHighlightSource();
185 if (!debugger_sp->GetUseColor())
191 const auto value = debugger_sp->GetStopShowColumn();
204 const auto value = debugger_sp->GetStopShowColumn();
214 return debugger_sp && debugger_sp->GetUseColor();
218 uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
219 const char *current_line_cstr,
Stream *s,
226 if (start_line == 0) {
243 const uint32_t end_line = start_line + count - 1;
244 for (uint32_t line = start_line; line <= end_line; ++line) {
245 if (!last_file_sp->LineIsValid(line)) {
255 prefix = llvm::formatv(
"[{0}]", bp_count);
261 snprintf(buffer,
sizeof(buffer),
"%2.2s",
262 (line == curr_line) ? current_line_cstr :
"");
263 std::string current_line_highlight(buffer);
268 (debugger_sp->GetStopShowLineMarkerAnsiPrefix() +
269 current_line_highlight +
270 debugger_sp->GetStopShowLineMarkerAnsiSuffix())
274 s->
Printf(
"%s%s %-4u\t", prefix.c_str(), current_line_highlight.c_str(),
280 std::optional<size_t> columnToHighlight;
281 if (line == curr_line && column)
282 columnToHighlight = column - 1;
284 size_t this_line_size =
285 last_file_sp->DisplaySourceLines(line, columnToHighlight, 0, 0, s);
286 if (column != 0 && line == curr_line &&
289 std::string src_line;
290 last_file_sp->GetLine(line, src_line);
293 for (
size_t i = 0; i + 1 < column && i < src_line.length(); ++i)
294 s->
PutChar(src_line[i] ==
'\t' ?
'\t' :
' ');
298 if (this_line_size == 0) {
308 const FileSpec &file_spec, uint32_t line, uint32_t column,
309 uint32_t context_before, uint32_t context_after,
310 const char *current_line_cstr,
Stream *s,
315 uint32_t count = context_before + context_after + 1;
316 if (line > context_before)
317 start_line = line - context_before;
322 if (last_file_sp.get() != file_sp.get()) {
328 start_line, count, line, column, current_line_cstr, s, bp_locs);
336 const bool have_default_file_line = last_file_sp &&
m_last_line > 0;
364 }
else if (have_default_file_line)
369 const uint32_t column = 0;
403 Module *executable_ptr = target_sp->GetExecutableModulePointer();
404 if (executable_ptr) {
413 lldb::eFunctionNameTypeBase,
414 function_options, sc_list);
418 if (sc.function->GetAddressRange()
420 .CalculateSymbolContextLineEntry(line_entry)) {
438 std::vector<uint32_t> &match_lines) {
443 return file_sp->FindLinesMatchingRegex(regex, start_line, end_line,
449 : m_file_spec_orig(file_spec), m_file_spec(), m_mod_time(),
450 m_debugger_wp(debugger_sp), m_target_wp(
TargetSP()) {
455 : m_file_spec_orig(file_spec), m_file_spec(), m_mod_time(),
456 m_debugger_wp(target_sp ? target_sp->GetDebugger().shared_from_this()
465 SetFileSpec(file_spec);
469 m_source_map_mod_id = target_sp->GetSourcePathMap().GetModificationID();
472 if (m_mod_time == llvm::sys::TimePoint<>()) {
476 bool check_inlines =
false;
479 target_sp->GetImages().ResolveSymbolContextForFilePath(
481 SymbolContextItem(eSymbolContextModule |
482 eSymbolContextCompUnit),
484 bool got_multiple =
false;
485 if (num_matches != 0) {
486 if (num_matches > 1) {
491 if (test_cu != sc.comp_unit)
495 test_cu = sc.comp_unit;
513 auto remapped = target_sp->GetSourcePathMap().FindFile(m_file_spec);
516 if (target_sp->GetImages().FindSourceFile(m_file_spec, new_spec))
520 SetFileSpec(*remapped);
526 if (m_mod_time != llvm::sys::TimePoint<>())
532 m_file_spec = std::move(file_spec);
543 if (CalculateLineOffsets(line)) {
544 if (line < m_offsets.size())
545 return m_offsets[line - 1];
551 CalculateLineOffsets();
552 return m_offsets.size();
556 if (!LineIsValid(line))
559 size_t line_offset = GetLineOffset(line);
560 if (line_offset < m_data_sp->GetByteSize())
561 return (
const char *)m_data_sp->GetBytes() + line_offset;
566 bool include_newline_chars) {
567 if (!LineIsValid(line))
570 size_t start_offset = GetLineOffset(line);
571 size_t end_offset = GetLineOffset(line + 1);
573 end_offset = m_data_sp->GetByteSize();
575 if (end_offset > start_offset) {
576 uint32_t length = end_offset - start_offset;
577 if (!include_newline_chars) {
578 const char *line_start =
579 (
const char *)m_data_sp->GetBytes() + start_offset;
581 const char last_char = line_start[length - 1];
582 if ((last_char ==
'\r') || (last_char ==
'\n'))
597 if (CalculateLineOffsets(line))
598 return line < m_offsets.size();
607 return curr_mod_time != llvm::sys::TimePoint<>() &&
608 m_mod_time != curr_mod_time;
613 return GetSourceMapModificationID() !=
614 target_sp->GetSourcePathMap().GetModificationID();
619 std::optional<size_t> column,
620 uint32_t context_before,
621 uint32_t context_after,
643 style.
selected.
Set(debugger_sp->GetStopShowColumnAnsiPrefix(),
644 debugger_sp->GetStopShowColumnAnsiSuffix());
647 std::string path = GetFileSpec().GetPath(
false);
652 const uint32_t start_line =
653 line <= context_before ? 1 : line - context_before;
654 const uint32_t start_line_offset = GetLineOffset(start_line);
656 const uint32_t end_line = line + context_after;
657 uint32_t end_line_offset = GetLineOffset(end_line + 1);
659 end_line_offset = m_data_sp->GetByteSize();
661 assert(start_line_offset <= end_line_offset);
662 if (start_line_offset < end_line_offset) {
663 size_t count = end_line_offset - start_line_offset;
664 const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
666 auto ref = llvm::StringRef(
reinterpret_cast<const char *
>(cstr), count);
668 h.Highlight(style, ref, column,
"", *s);
680 std::vector<uint32_t> &match_lines) {
683 if (!LineIsValid(start_line) ||
684 (end_line !=
UINT32_MAX && !LineIsValid(end_line)))
686 if (start_line > end_line)
689 for (uint32_t line_no = start_line; line_no < end_line; line_no++) {
691 if (!GetLine(line_no, buffer))
694 match_lines.push_back(line_no);
711 if (!m_offsets.empty() && m_offsets[0] ==
UINT32_MAX)
714 if (m_offsets.empty()) {
715 if (m_data_sp.get() ==
nullptr)
718 const char *start = (
const char *)m_data_sp->GetBytes();
720 const char *end = start + m_data_sp->GetByteSize();
728 for (s = start; s < end; ++s) {
734 if (curr_ch != next_ch)
738 m_offsets.push_back(s + 1 - start);
741 if (!m_offsets.empty()) {
742 if (m_offsets.back() < size_t(end - start))
743 m_offsets.push_back(end - start);
749 assert(
"Not implemented yet" &&
false);
754 assert(
"Not implemented yet" &&
false);
760 if (!LineIsValid(line_no))
763 size_t start_offset = GetLineOffset(line_no);
764 size_t end_offset = GetLineOffset(line_no + 1);
766 end_offset = m_data_sp->GetByteSize();
768 buffer.assign((
const char *)m_data_sp->GetBytes() + start_offset,
769 end_offset - start_offset);
776 llvm::sys::ScopedWriter guard(m_mutex);
778 assert(file_sp &&
"invalid FileSP");
780 AddSourceFileImpl(file_spec, file_sp);
781 const FileSpec &resolved_file_spec = file_sp->GetFileSpec();
782 if (file_spec != resolved_file_spec)
783 AddSourceFileImpl(file_sp->GetFileSpec(), file_sp);
787 llvm::sys::ScopedWriter guard(m_mutex);
789 assert(file_sp &&
"invalid FileSP");
793 auto it = m_file_cache.begin();
794 while (it != m_file_cache.end()) {
795 if (it->second == file_sp)
796 it = m_file_cache.erase(it);
804 FileCache::iterator pos = m_file_cache.find(file_spec);
805 if (pos == m_file_cache.end()) {
806 m_file_cache[file_spec] = file_sp;
808 if (file_sp != pos->second)
809 m_file_cache[file_spec] = file_sp;
815 llvm::sys::ScopedReader guard(m_mutex);
817 FileCache::const_iterator pos = m_file_cache.find(file_spec);
818 if (pos != m_file_cache.end())
824 stream <<
"Modification time Lines Path\n";
825 stream <<
"------------------- -------- --------------------------------\n";
826 for (
auto &entry : m_file_cache) {
829 FileSP file = entry.second;
830 stream.
Format(
"{0:%Y-%m-%d %H:%M:%S} {1,8:d} {2}\n", file->GetTimestamp(),
831 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 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)
A class that describes a compilation unit.
const FileSpec & GetPrimaryFile() const
Return the primary source spec 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.
"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)
void SetFileSpec(FileSpec file_spec)
Set file and update modification time.
const char * PeekLineData(uint32_t line)
bool LineIsValid(uint32_t line)
bool PathRemappingIsStale() const
void CommonInitializer(const FileSpec &file_spec, lldb::TargetSP target_sp)
uint32_t GetLineLength(uint32_t line, bool include_newline_chars)
bool CalculateLineOffsets(uint32_t line=UINT32_MAX)
bool GetLine(uint32_t line_no, std::string &buffer)
uint32_t GetLineOffset(uint32_t line)
size_t DisplaySourceLines(uint32_t line, std::optional< size_t > column, uint32_t context_before, uint32_t context_after, Stream *s)
File(const FileSpec &file_spec, lldb::TargetSP target_sp)
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)
FileSpec m_last_file_spec
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)
bool SetDefaultFileAndLine(const FileSpec &file_spec, uint32_t line)
std::shared_ptr< File > FileSP
size_t DisplaySourceLinesWithLineNumbers(const FileSpec &file, 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)
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
void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector< uint32_t > &match_lines)
bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line)
FileSP GetFile(const FileSpec &file_spec)
size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse, 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
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)
@ 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.
const FileSpec & GetFile() const
Helper to access the file.
Options used by Module::FindFunctions.
bool include_inlines
Include inlined functions.
bool include_symbols
Include the symbol table.