X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsource.c;h=8ebc4361e17104186db4d31ca738a276bd4a44be;hb=268a13a5a3f7c6b9b6ffc5ac2d1b24eb41f3fbdc;hp=c75351e65f4e0c48b64e55af7bd388bff8a1b25f;hpb=95b1f9ac6b7de84b09580bdf2456955bcff86da1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/source.c b/gdb/source.c index c75351e65f..8ebc4361e1 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1,5 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986-2018 Free Software Foundation, Inc. + Copyright (C) 1986-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -26,7 +26,7 @@ #include "gdbcmd.h" #include "frame.h" #include "value.h" -#include "filestuff.h" +#include "gdbsupport/filestuff.h" #include #include @@ -41,10 +41,11 @@ #include "completer.h" #include "ui-out.h" #include "readline/readline.h" -#include "common/enum-flags.h" -#include "common/scoped_fd.h" +#include "gdbsupport/enum-flags.h" +#include "gdbsupport/scoped_fd.h" #include -#include "common/pathstuff.h" +#include "gdbsupport/pathstuff.h" +#include "source-cache.h" #define OPEN_MODE (O_RDONLY | O_BINARY) #define FDOPEN_MODE FOPEN_RB @@ -232,20 +233,11 @@ clear_current_source_symtab_and_line (void) current_source_line = 0; } -/* Set the source file default for the "list" command to be S. - - If S is NULL, and we don't have a default, find one. This - should only be called when the user actually tries to use the - default, since we produce an error if we can't find a reasonable - default. Also, since this can cause symbols to be read, doing it - before we need to would make things slower than necessary. */ +/* See source.h. */ void select_source_symtab (struct symtab *s) { - struct objfile *ofp; - struct compunit_symtab *cu; - if (s) { current_source_symtab = s; @@ -277,29 +269,35 @@ select_source_symtab (struct symtab *s) current_source_line = 1; - ALL_FILETABS (ofp, cu, s) + for (objfile *ofp : current_program_space->objfiles ()) { - const char *name = s->filename; - int len = strlen (name); - - if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0 - || strcmp (name, "<>") == 0))) + for (compunit_symtab *cu : ofp->compunits ()) { - current_source_pspace = current_program_space; - current_source_symtab = s; + for (symtab *symtab : compunit_filetabs (cu)) + { + const char *name = symtab->filename; + int len = strlen (name); + + if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0 + || strcmp (name, "<>") == 0))) + { + current_source_pspace = current_program_space; + current_source_symtab = symtab; + } + } } } if (current_source_symtab) return; - ALL_OBJFILES (ofp) - { - if (ofp->sf) - s = ofp->sf->qf->find_last_source_symtab (ofp); - if (s) - current_source_symtab = s; - } + for (objfile *objfile : current_program_space->objfiles ()) + { + if (objfile->sf) + s = objfile->sf->qf->find_last_source_symtab (objfile); + if (s) + current_source_symtab = s; + } if (current_source_symtab) return; @@ -350,26 +348,25 @@ show_directories_command (struct ui_file *file, int from_tty, show_directories_1 (NULL, from_tty); } -/* Forget line positions and file names for the symtabs in a - particular objfile. */ +/* See source.h. */ void forget_cached_source_info_for_objfile (struct objfile *objfile) { - struct compunit_symtab *cu; - struct symtab *s; - - ALL_OBJFILE_FILETABS (objfile, cu, s) + for (compunit_symtab *cu : objfile->compunits ()) { - if (s->line_charpos != NULL) + for (symtab *s : compunit_filetabs (cu)) { - xfree (s->line_charpos); - s->line_charpos = NULL; - } - if (s->fullname != NULL) - { - xfree (s->fullname); - s->fullname = NULL; + if (s->line_charpos != NULL) + { + xfree (s->line_charpos); + s->line_charpos = NULL; + } + if (s->fullname != NULL) + { + xfree (s->fullname); + s->fullname = NULL; + } } } @@ -377,22 +374,20 @@ forget_cached_source_info_for_objfile (struct objfile *objfile) objfile->sf->qf->forget_cached_source_info (objfile); } -/* Forget what we learned about line positions in source files, and - which directories contain them; must check again now since files - may be found in a different directory now. */ +/* See source.h. */ void forget_cached_source_info (void) { struct program_space *pspace; - struct objfile *objfile; ALL_PSPACES (pspace) - ALL_PSPACE_OBJFILES (pspace, objfile) - { - forget_cached_source_info_for_objfile (objfile); - } + for (objfile *objfile : pspace->objfiles ()) + { + forget_cached_source_info_for_objfile (objfile); + } + g_source_cache.clear (); last_source_visited = NULL; } @@ -992,7 +987,10 @@ find_and_open_source (const char *filename, result = gdb_open_cloexec (fullname->get (), OPEN_MODE, 0); if (result >= 0) { - *fullname = gdb_realpath (fullname->get ()); + if (basenames_may_differ) + *fullname = gdb_realpath (fullname->get ()); + else + *fullname = gdb_abspath (fullname->get ()); return scoped_fd (result); } @@ -1014,9 +1012,7 @@ find_and_open_source (const char *filename, /* Replace a path entry of $cdir with the compilation directory name. */ #define cdir_len 5 - /* We cast strstr's result in case an ANSIhole has made it const, - which produces a "required warning" when assigned to a nonconst. */ - p = (char *) strstr (source_path, "$cdir"); + p = strstr (source_path, "$cdir"); if (p && (p == path || p[-1] == DIRNAME_SEPARATOR) && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0')) { @@ -1032,26 +1028,22 @@ find_and_open_source (const char *filename, } } - gdb::unique_xmalloc_ptr rewritten_filename; - if (IS_ABSOLUTE_PATH (filename)) - { - /* If filename is absolute path, try the source path - substitution on it. */ - rewritten_filename = rewrite_source_path (filename); + gdb::unique_xmalloc_ptr rewritten_filename + = rewrite_source_path (filename); - if (rewritten_filename != NULL) - filename = rewritten_filename.get (); - } + if (rewritten_filename != NULL) + filename = rewritten_filename.get (); - result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename, - OPEN_MODE, fullname); + openp_flags flags = OPF_SEARCH_IN_PATH; + if (basenames_may_differ) + flags |= OPF_RETURN_REALPATH; + result = openp (path, flags, filename, OPEN_MODE, fullname); if (result < 0) { /* Didn't work. Try using just the basename. */ p = lbasename (filename); if (p != filename) - result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, p, - OPEN_MODE, fullname); + result = openp (path, flags, p, OPEN_MODE, fullname); } return scoped_fd (result); @@ -1137,7 +1129,7 @@ symtab_to_filename_for_display (struct symtab *symtab) to be open on descriptor DESC. All set S->nlines to the number of such lines. */ -void +static void find_source_lines (struct symtab *s, int desc) { struct stat st; @@ -1204,54 +1196,20 @@ find_source_lines (struct symtab *s, int desc) -/* Get full pathname and line number positions for a symtab. - Set *FULLNAME to actual name of the file as found by `openp', - or to 0 if the file is not found. */ - -static void -get_filename_and_charpos (struct symtab *s, char **fullname) -{ - scoped_fd desc = open_source_file (s); - if (desc.get () < 0) - { - if (fullname) - *fullname = NULL; - return; - } - if (fullname) - *fullname = s->fullname; - if (s->line_charpos == 0) - find_source_lines (s, desc.get ()); -} - -/* Print text describing the full name of the source file S - and the line number LINE and its corresponding character position. - The text starts with two Ctrl-z so that the Emacs-GDB interface - can easily find it. - - MID_STATEMENT is nonzero if the PC is not at the beginning of that line. - - Return 1 if successful, 0 if could not find the file. */ +/* See source.h. */ -int -identify_source_line (struct symtab *s, int line, int mid_statement, - CORE_ADDR pc) +scoped_fd +open_source_file_with_line_charpos (struct symtab *s) { - if (s->line_charpos == 0) - get_filename_and_charpos (s, (char **) NULL); - if (s->fullname == 0) - return 0; - if (line > s->nlines) - /* Don't index off the end of the line_charpos array. */ - return 0; - annotate_source (s->fullname, line, s->line_charpos[line - 1], - mid_statement, get_objfile_arch (SYMTAB_OBJFILE (s)), pc); + scoped_fd fd (open_source_file (s)); + if (fd.get () < 0) + return fd; - current_source_line = line; - current_source_symtab = s; - clear_lines_listed_range (); - return 1; + if (s->line_charpos == nullptr) + find_source_lines (s, fd.get ()); + return fd; } + /* Print source lines from the file of symtab S, @@ -1261,7 +1219,6 @@ static void print_source_lines_base (struct symtab *s, int line, int stopline, print_source_lines_flags flags) { - int c; scoped_fd desc; int noprint = 0; int nlines = stopline - line; @@ -1320,7 +1277,8 @@ print_source_lines_base (struct symtab *s, int line, int stopline, MI expects both fields. ui_source_list is set only for CLI, not for TUI. */ if (uiout->is_mi_like_p () || uiout->test_flags (ui_source_list)) - uiout->field_string ("file", symtab_to_filename_for_display (s)); + uiout->field_string ("file", symtab_to_filename_for_display (s), + ui_out_style_kind::FILE); if (uiout->is_mi_like_p () || !uiout->test_flags (ui_source_list)) { const char *s_fullname = symtab_to_fullname (s); @@ -1343,26 +1301,21 @@ print_source_lines_base (struct symtab *s, int line, int stopline, last_source_error = 0; - if (s->line_charpos == 0) - find_source_lines (s, desc.get ()); + /* If the user requested a sequence of lines that seems to go backward + (from high to low line numbers) then we don't print anything. */ + if (stopline <= line) + return; - if (line < 1 || line > s->nlines) + std::string lines; + if (!g_source_cache.get_source_lines (s, line, stopline - 1, &lines)) error (_("Line number %d out of range; %s has %d lines."), line, symtab_to_filename_for_display (s), s->nlines); - if (lseek (desc.get (), s->line_charpos[line - 1], 0) < 0) - perror_with_name (symtab_to_filename_for_display (s)); - - gdb_file_up stream = desc.to_file (FDOPEN_MODE); - clearerr (stream.get ()); - - while (nlines-- > 0) + const char *iter = lines.c_str (); + while (nlines-- > 0 && *iter != '\0') { char buf[20]; - c = fgetc (stream.get ()); - if (c == EOF) - break; last_line_listed = current_source_line; if (flags & PRINT_SOURCE_LINES_FILENAME) { @@ -1371,39 +1324,63 @@ print_source_lines_base (struct symtab *s, int line, int stopline, } xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++); uiout->text (buf); - do + + while (*iter != '\0') { - if (c < 040 && c != '\t' && c != '\n' && c != '\r') + /* Find a run of characters that can be emitted at once. + This is done so that escape sequences are kept + together. */ + const char *start = iter; + while (true) { - xsnprintf (buf, sizeof (buf), "^%c", c + 0100); - uiout->text (buf); + int skip_bytes; + + char c = *iter; + if (c == '\033' && skip_ansi_escape (iter, &skip_bytes)) + iter += skip_bytes; + else if (c >= 0 && c < 040 && c != '\t') + break; + else if (c == 0177) + break; + else + ++iter; } - else if (c == 0177) - uiout->text ("^?"); - else if (c == '\r') + if (iter > start) { - /* Skip a \r character, but only before a \n. */ - int c1 = fgetc (stream.get ()); - - if (c1 != '\n') - printf_filtered ("^%c", c + 0100); - if (c1 != EOF) - ungetc (c1, stream.get ()); + std::string text (start, iter); + uiout->text (text.c_str ()); } - else + if (*iter == '\r') + { + /* Treat either \r or \r\n as a single newline. */ + ++iter; + if (*iter == '\n') + ++iter; + break; + } + else if (*iter == '\n') { - xsnprintf (buf, sizeof (buf), "%c", c); + ++iter; + break; + } + else if (*iter > 0 && *iter < 040) + { + xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100); uiout->text (buf); + ++iter; + } + else if (*iter == 0177) + { + uiout->text ("^?"); + ++iter; } } - while (c != '\n' && (c = fgetc (stream.get ())) >= 0); + uiout->text ("\n"); } } -/* Show source lines from the file of symtab S, starting with line - number LINE and stopping before line number STOPLINE. If this is - not the command line version, then the source is shown in the source - window otherwise it is simply printed. */ + +/* See source.h. */ void print_source_lines (struct symtab *s, int line, int stopline, @@ -1411,6 +1388,18 @@ print_source_lines (struct symtab *s, int line, int stopline, { print_source_lines_base (s, line, stopline, flags); } + +/* See source.h. */ + +void +print_source_lines (struct symtab *s, source_lines_range line_range, + print_source_lines_flags flags) +{ + print_source_lines_base (s, line_range.startline (), + line_range.stopline (), flags); +} + + /* Print info on range of pc's in a specified line. */ @@ -1507,8 +1496,8 @@ info_line_command (const char *arg, int from_tty) /* If this is the only line, show the source code. If it could not find the file, don't do anything special. */ - if (annotation_level && sals.size () == 1) - identify_source_line (sal.symtab, sal.line, 0, start_pc); + if (sals.size () == 1) + annotate_source_line (sal.symtab, sal.line, 0, start_pc); } else /* Is there any case in which we get here, and have an address @@ -1521,28 +1510,27 @@ info_line_command (const char *arg, int from_tty) /* Commands to search the source file for a regexp. */ +/* Helper for forward_search_command/reverse_search_command. FORWARD + indicates direction: true for forward, false for + backward/reverse. */ + static void -forward_search_command (const char *regex, int from_tty) +search_command_helper (const char *regex, int from_tty, bool forward) { - int c; - int line; - char *msg; - - line = last_line_listed + 1; - - msg = (char *) re_comp (regex); + const char *msg = re_comp (regex); if (msg) error (("%s"), msg); if (current_source_symtab == 0) select_source_symtab (0); - scoped_fd desc = open_source_file (current_source_symtab); + scoped_fd desc (open_source_file_with_line_charpos (current_source_symtab)); if (desc.get () < 0) perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc.get ()); + int line = (forward + ? last_line_listed + 1 + : last_line_listed - 1); if (line < 1 || line > current_source_symtab->nlines) error (_("Expression not found")); @@ -1553,43 +1541,35 @@ forward_search_command (const char *regex, int from_tty) gdb_file_up stream = desc.to_file (FDOPEN_MODE); clearerr (stream.get ()); + + gdb::def_vector buf; + buf.reserve (256); + while (1) { - static char *buf = NULL; - char *p; - int cursize, newsize; + buf.resize (0); - cursize = 256; - buf = (char *) xrealloc (buf, cursize); - p = buf; - - c = fgetc (stream.get ()); + int c = fgetc (stream.get ()); if (c == EOF) break; do { - *p++ = c; - if (p - buf == cursize) - { - newsize = cursize + cursize / 2; - buf = (char *) xrealloc (buf, newsize); - p = buf + cursize; - cursize = newsize; - } + buf.push_back (c); } while (c != '\n' && (c = fgetc (stream.get ())) >= 0); /* Remove the \r, if any, at the end of the line, otherwise regular expressions that end with $ or \n won't work. */ - if (p - buf > 1 && p[-2] == '\r') + size_t sz = buf.size (); + if (sz >= 2 && buf[sz - 2] == '\r') { - p--; - p[-1] = '\n'; + buf[sz - 2] = '\n'; + buf.resize (sz - 1); } /* We now have a source line in buf, null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) + buf.push_back ('\0'); + if (re_exec (buf.data ()) > 0) { /* Match! */ print_source_lines (current_source_symtab, line, line + 1, 0); @@ -1597,90 +1577,37 @@ forward_search_command (const char *regex, int from_tty) current_source_line = std::max (line - lines_to_list / 2, 1); return; } - line++; + + if (forward) + line++; + else + { + line--; + if (line < 1) + break; + if (fseek (stream.get (), + current_source_symtab->line_charpos[line - 1], 0) < 0) + { + const char *filename + = symtab_to_filename_for_display (current_source_symtab); + perror_with_name (filename); + } + } } printf_filtered (_("Expression not found\n")); } static void -reverse_search_command (const char *regex, int from_tty) +forward_search_command (const char *regex, int from_tty) { - int c; - int line; - char *msg; - - line = last_line_listed - 1; - - msg = (char *) re_comp (regex); - if (msg) - error (("%s"), msg); - - if (current_source_symtab == 0) - select_source_symtab (0); - - scoped_fd desc = open_source_file (current_source_symtab); - if (desc.get () < 0) - perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - - if (current_source_symtab->line_charpos == 0) - find_source_lines (current_source_symtab, desc.get ()); - - if (line < 1 || line > current_source_symtab->nlines) - error (_("Expression not found")); - - if (lseek (desc.get (), current_source_symtab->line_charpos[line - 1], 0) - < 0) - perror_with_name (symtab_to_filename_for_display (current_source_symtab)); - - gdb_file_up stream = desc.to_file (FDOPEN_MODE); - clearerr (stream.get ()); - while (line > 1) - { -/* FIXME!!! We walk right off the end of buf if we get a long line!!! */ - char buf[4096]; /* Should be reasonable??? */ - char *p = buf; - - c = fgetc (stream.get ()); - if (c == EOF) - break; - do - { - *p++ = c; - } - while (c != '\n' && (c = fgetc (stream.get ())) >= 0); - - /* Remove the \r, if any, at the end of the line, otherwise - regular expressions that end with $ or \n won't work. */ - if (p - buf > 1 && p[-2] == '\r') - { - p--; - p[-1] = '\n'; - } - - /* We now have a source line in buf; null terminate and match. */ - *p = 0; - if (re_exec (buf) > 0) - { - /* Match! */ - print_source_lines (current_source_symtab, line, line + 1, 0); - set_internalvar_integer (lookup_internalvar ("_"), line); - current_source_line = std::max (line - lines_to_list / 2, 1); - return; - } - line--; - if (fseek (stream.get (), - current_source_symtab->line_charpos[line - 1], 0) < 0) - { - const char *filename; - - filename = symtab_to_filename_for_display (current_source_symtab); - perror_with_name (filename); - } - } + search_command_helper (regex, from_tty, true); +} - printf_filtered (_("Expression not found\n")); - return; +static void +reverse_search_command (const char *regex, int from_tty) +{ + search_command_helper (regex, from_tty, false); } /* If the last character of PATH is a directory separator, then strip it. */ @@ -1893,6 +1820,33 @@ set_substitute_path_command (const char *args, int from_tty) forget_cached_source_info (); } +/* See source.h. */ + +source_lines_range::source_lines_range (int startline, + source_lines_range::direction dir) +{ + if (dir == source_lines_range::FORWARD) + { + LONGEST end = static_cast (startline) + get_lines_to_list (); + + if (end > INT_MAX) + end = INT_MAX; + + m_startline = startline; + m_stopline = static_cast (end); + } + else + { + LONGEST start = static_cast (startline) - get_lines_to_list (); + + if (start < 1) + start = 1; + + m_startline = static_cast (start); + m_stopline = startline; + } +} + void _initialize_source (void)