X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsource.c;h=7de86b4925161652aac2dd708dfc925cc14917d6;hb=1c658ad5fac2a221b589cbe26ec84c788b24a8d1;hp=4eda082f15d0ad5354bdd8eaf9618a89aa05958b;hpb=82ae4854632a42a7d7d74b6cdb8da9be7890976c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/source.c b/gdb/source.c index 4eda082f15..7de86b4925 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1,7 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -245,7 +243,7 @@ select_source_symtab (struct symtab *s) if one exists. */ if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0)) { - sals = decode_line_spec (main_name (), 1); + sals = decode_line_spec (main_name (), DECODE_LINE_FUNFIRSTLINE); sal = sals.sals[0]; xfree (sals.sals); current_source_pspace = sal.pspace; @@ -335,6 +333,32 @@ 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. */ + +void +forget_cached_source_info_for_objfile (struct objfile *objfile) +{ + struct symtab *s; + + ALL_OBJFILE_SYMTABS (objfile, s) + { + if (s->line_charpos != NULL) + { + xfree (s->line_charpos); + s->line_charpos = NULL; + } + if (s->fullname != NULL) + { + xfree (s->fullname); + s->fullname = NULL; + } + } + + if (objfile->sf) + 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. */ @@ -343,28 +367,12 @@ void forget_cached_source_info (void) { struct program_space *pspace; - struct symtab *s; struct objfile *objfile; ALL_PSPACES (pspace) ALL_PSPACE_OBJFILES (pspace, objfile) { - for (s = objfile->symtabs; s != NULL; s = s->next) - { - if (s->line_charpos != NULL) - { - xfree (s->line_charpos); - s->line_charpos = NULL; - } - if (s->fullname != NULL) - { - xfree (s->fullname); - s->fullname = NULL; - } - } - - if (objfile->sf) - objfile->sf->qf->forget_cached_source_info (objfile); + forget_cached_source_info_for_objfile (objfile); } last_source_visited = NULL; @@ -432,62 +440,40 @@ add_path (char *dirname, char **which_path, int parse_separators) { char *old = *which_path; int prefix = 0; - char **argv = NULL; - char *arg; - int argv_index = 0; + VEC (char_ptr) *dir_vec = NULL; + struct cleanup *back_to; + int ix; + char *name; if (dirname == 0) return; if (parse_separators) { + char **argv, **argvp; + /* This will properly parse the space and tab separators - and any quotes that may exist. DIRNAME_SEPARATOR will - be dealt with later. */ + and any quotes that may exist. */ argv = gdb_buildargv (dirname); - make_cleanup_freeargv (argv); - arg = argv[0]; + for (argvp = argv; *argvp; argvp++) + dirnames_to_char_ptr_vec_append (&dir_vec, *argvp); + + freeargv (argv); } else - { - arg = xstrdup (dirname); - make_cleanup (xfree, arg); - } + VEC_safe_push (char_ptr, dir_vec, xstrdup (dirname)); + back_to = make_cleanup_free_char_ptr_vec (dir_vec); - do + for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, name); ++ix) { - char *name = arg; char *p; struct stat st; - { - char *separator = NULL; - - /* Spaces and tabs will have been removed by buildargv(). - The directories will there be split into a list but - each entry may still contain DIRNAME_SEPARATOR. */ - if (parse_separators) - separator = strchr (name, DIRNAME_SEPARATOR); - - if (separator == 0) - p = arg = name + strlen (name); - else - { - p = separator; - arg = p + 1; - while (*arg == DIRNAME_SEPARATOR) - ++arg; - } - - /* If there are no more directories in this argument then start - on the next argument next time round the loop (if any). */ - if (*arg == '\0') - arg = parse_separators ? argv[++argv_index] : NULL; - } - - /* name is the start of the directory. - p is the separator (or null) following the end. */ + /* Spaces and tabs will have been removed by buildargv(). + NAME is the start of the directory. + P is the '\0' following the end. */ + p = name + strlen (name); while (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */ #ifdef HAVE_DOS_BASED_FILE_SYSTEM @@ -565,69 +551,54 @@ add_path (char *dirname, char **which_path, int parse_separators) append: { unsigned int len = strlen (name); + char tinybuf[2]; p = *which_path; - while (1) + /* FIXME: we should use realpath() or its work-alike + before comparing. Then all the code above which + removes excess slashes and dots could simply go away. */ + if (!filename_cmp (p, name)) { - /* FIXME: strncmp loses in interesting ways on MS-DOS and - MS-Windows because of case-insensitivity and two different - but functionally identical slash characters. We need a - special filesystem-dependent file-name comparison function. - - Actually, even on Unix I would use realpath() or its work- - alike before comparing. Then all the code above which - removes excess slashes and dots could simply go away. */ - if (!strncmp (p, name, len) - && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR)) - { - /* Found it in the search path, remove old copy. */ - if (p > *which_path) - p--; /* Back over leading separator. */ - if (prefix > p - *which_path) - goto skip_dup; /* Same dir twice in one cmd. */ - strcpy (p, &p[len + 1]); /* Copy from next \0 or : */ - } - p = strchr (p, DIRNAME_SEPARATOR); - if (p != 0) - ++p; - else - break; + /* Found it in the search path, remove old copy. */ + if (p > *which_path) + p--; /* Back over leading separator. */ + if (prefix > p - *which_path) + goto skip_dup; /* Same dir twice in one cmd. */ + memmove (p, &p[len + 1], strlen (&p[len + 1]) + 1); /* Copy from next \0 or : */ } - if (p == 0) - { - char tinybuf[2]; - tinybuf[0] = DIRNAME_SEPARATOR; - tinybuf[1] = '\0'; + tinybuf[0] = DIRNAME_SEPARATOR; + tinybuf[1] = '\0'; - /* If we have already tacked on a name(s) in this command, - be sure they stay on the front as we tack on some - more. */ - if (prefix) - { - char *temp, c; - - c = old[prefix]; - old[prefix] = '\0'; - temp = concat (old, tinybuf, name, (char *)NULL); - old[prefix] = c; - *which_path = concat (temp, "", &old[prefix], (char *) NULL); - prefix = strlen (temp); - xfree (temp); - } - else - { - *which_path = concat (name, (old[0] ? tinybuf : old), - old, (char *)NULL); - prefix = strlen (name); - } - xfree (old); - old = *which_path; + /* If we have already tacked on a name(s) in this command, + be sure they stay on the front as we tack on some + more. */ + if (prefix) + { + char *temp, c; + + c = old[prefix]; + old[prefix] = '\0'; + temp = concat (old, tinybuf, name, (char *)NULL); + old[prefix] = c; + *which_path = concat (temp, "", &old[prefix], (char *) NULL); + prefix = strlen (temp); + xfree (temp); } + else + { + *which_path = concat (name, (old[0] ? tinybuf : old), + old, (char *)NULL); + prefix = strlen (name); + } + xfree (old); + old = *which_path; } skip_dup: + ; } - while (arg != NULL); + + do_cleanups (back_to); } @@ -708,10 +679,11 @@ openp (const char *path, int opts, const char *string, { int fd; char *filename; - const char *p; - const char *p1; - int len; int alloclen; + VEC (char_ptr) *dir_vec; + struct cleanup *back_to; + int ix; + char *dir; /* The open syscall MODE parameter is not specified. */ gdb_assert ((mode & O_CREAT) == 0); @@ -774,16 +746,15 @@ openp (const char *path, int opts, const char *string, alloclen = strlen (path) + strlen (string) + 2; filename = alloca (alloclen); fd = -1; - for (p = path; p; p = p1 ? p1 + 1 : 0) + + dir_vec = dirnames_to_char_ptr_vec (path); + back_to = make_cleanup_free_char_ptr_vec (dir_vec); + + for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix) { - p1 = strchr (p, DIRNAME_SEPARATOR); - if (p1) - len = p1 - p; - else - len = strlen (p); + size_t len = strlen (dir); - if (len == 4 && p[0] == '$' && p[1] == 'c' - && p[2] == 'w' && p[3] == 'd') + if (strcmp (dir, "$cwd") == 0) { /* Name is $cwd -- insert current directory name instead. */ int newlen; @@ -798,11 +769,29 @@ openp (const char *path, int opts, const char *string, } strcpy (filename, current_directory); } + else if (strchr(dir, '~')) + { + /* See whether we need to expand the tilde. */ + int newlen; + char *tilde_expanded; + + tilde_expanded = tilde_expand (dir); + + /* First, realloc the filename buffer if too short. */ + len = strlen (tilde_expanded); + newlen = len + strlen (string) + 2; + if (newlen > alloclen) + { + alloclen = newlen; + filename = alloca (alloclen); + } + strcpy (filename, tilde_expanded); + xfree (tilde_expanded); + } else { /* Normal file name in path -- just use it. */ - strncpy (filename, p, len); - filename[len] = 0; + strcpy (filename, dir); /* Don't search $cdir. It's also a magic path like $cwd, but we don't have enough information to expand it. The user *could* @@ -811,7 +800,7 @@ openp (const char *path, int opts, const char *string, contexts. If the user really has '$cdir' one can use './$cdir'. We can get $cdir when loading scripts. When loading source files $cdir must have already been expanded to the correct value. */ - if (strcmp (filename, "$cdir") == 0) + if (strcmp (dir, "$cdir") == 0) continue; } @@ -830,6 +819,8 @@ openp (const char *path, int opts, const char *string, } } + do_cleanups (back_to); + done: if (filename_opened) { @@ -967,26 +958,6 @@ rewrite_source_path (const char *path) return new_path; } -/* This function is capable of finding the absolute path to a - source file, and opening it, provided you give it a FILENAME. Both the - DIRNAME and FULLNAME are only added suggestions on where to find the file. - - FILENAME should be the filename to open. - DIRNAME is the compilation directory of a particular source file. - Only some debug formats provide this info. - FULLNAME can be the last known absolute path to the file in question. - Space for the path must have been malloc'd. If a path substitution - is applied we free the old value and set a new one. - - On Success - A valid file descriptor is returned (the return value is positive). - FULLNAME is set to the absolute path to the file just opened. - The caller is responsible for freeing FULLNAME. - - On Failure - An invalid file descriptor is returned (the return value is negative). - FULLNAME is set to NULL. */ - int find_and_open_source (const char *filename, const char *dirname, @@ -1013,7 +984,16 @@ find_and_open_source (const char *filename, result = open (*fullname, OPEN_MODE); if (result >= 0) - return result; + { + /* Call xfullpath here to be consistent with openp + which we use below. */ + char *lpath = xfullpath (*fullname); + + xfree (*fullname); + *fullname = lpath; + return result; + } + /* Didn't work -- free old one, try again. */ xfree (*fullname); *fullname = NULL; @@ -1099,6 +1079,7 @@ open_source_file (struct symtab *s) If this function fails to find the file that this symtab represents, NULL will be returned and s->fullname will be set to NULL. */ + char * symtab_to_fullname (struct symtab *s) { @@ -1107,8 +1088,12 @@ symtab_to_fullname (struct symtab *s) if (!s) return NULL; - /* Don't check s->fullname here, the file could have been - deleted/moved/..., look for it again. */ + /* Use cached copy if we have it. + We rely on forget_cached_source_info being called appropriately + to handle cases like the file being moved. */ + if (s->fullname) + return s->fullname; + r = find_and_open_source (s->filename, s->dirname, &s->fullname); if (r >= 0) @@ -1149,30 +1134,6 @@ find_source_lines (struct symtab *s, int desc) if (mtime && mtime < st.st_mtime) warning (_("Source file is more recent than executable.")); -#ifdef LSEEK_NOT_LINEAR - { - char c; - - /* Have to read it byte by byte to find out where the chars live. */ - - line_charpos[0] = lseek (desc, 0, SEEK_CUR); - nlines = 1; - while (myread (desc, &c, 1) > 0) - { - if (c == '\n') - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = - (int *) xrealloc ((char *) line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR); - } - } - } -#else /* lseek linear. */ { struct cleanup *old_cleanups; @@ -1211,53 +1172,13 @@ find_source_lines (struct symtab *s, int desc) } do_cleanups (old_cleanups); } -#endif /* lseek linear. */ + s->nlines = nlines; s->line_charpos = (int *) xrealloc ((char *) line_charpos, nlines * sizeof (int)); } -/* Return the character position of a line LINE in symtab S. - Return 0 if anything is invalid. */ - -#if 0 /* Currently unused */ - -int -source_line_charpos (struct symtab *s, int line) -{ - if (!s) - return 0; - if (!s->line_charpos || line <= 0) - return 0; - if (line > s->nlines) - line = s->nlines; - return s->line_charpos[line - 1]; -} - -/* Return the line number of character position POS in symtab S. */ - -int -source_charpos_line (struct symtab *s, int chr) -{ - int line = 0; - int *lnp; - - if (s == 0 || s->line_charpos == 0) - return 0; - lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok. */ - while (line < s->nlines && *lnp <= chr) - { - line++; - lnp++; - } - if (line >= s->nlines) - line = s->nlines; - return line; -} - -#endif /* 0 */ /* Get full pathname and line number positions for a symtab. @@ -1334,6 +1255,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) FILE *stream; int nlines = stopline - line; struct cleanup *cleanup; + struct ui_out *uiout = current_uiout; /* Regardless of whether we can open the file, set current_source_symtab. */ current_source_symtab = s; @@ -1374,10 +1296,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) print_sys_errmsg (name, errno); } else - ui_out_field_int (uiout, "line", line); - ui_out_text (uiout, "\tin "); - ui_out_field_string (uiout, "file", s->filename); - ui_out_text (uiout, "\n"); + { + ui_out_field_int (uiout, "line", line); + ui_out_text (uiout, "\tin "); + ui_out_field_string (uiout, "file", s->filename); + ui_out_text (uiout, "\n"); + } return; } @@ -1465,12 +1389,14 @@ line_info (char *arg, int from_tty) struct symtab_and_line sal; CORE_ADDR start_pc, end_pc; int i; + struct cleanup *cleanups; init_sal (&sal); /* initialize to zeroes */ if (arg == 0) { sal.symtab = current_source_symtab; + sal.pspace = current_program_space; sal.line = last_line_listed; sals.nelts = 1; sals.sals = (struct symtab_and_line *) @@ -1479,16 +1405,20 @@ line_info (char *arg, int from_tty) } else { - sals = decode_line_spec_1 (arg, 0); + sals = decode_line_spec_1 (arg, DECODE_LINE_LIST_MODE); dont_repeat (); } + cleanups = make_cleanup (xfree, sals.sals); + /* C++ More than one line may have been specified, as when the user specifies an overloaded function name. Print info on them all. */ for (i = 0; i < sals.nelts; i++) { sal = sals.sals[i]; + if (sal.pspace != current_program_space) + continue; if (sal.symtab == 0) { @@ -1554,7 +1484,7 @@ line_info (char *arg, int from_tty) printf_filtered (_("Line number %d is out of range for \"%s\".\n"), sal.line, sal.symtab->filename); } - xfree (sals.sals); + do_cleanups (cleanups); } /* Commands to search the source file for a regexp. */