hrp@boring.cray.com (Hal Peterson) (09/23/89)
I am getting intermittent failures in GNU Make 3.55+, compiled with GCC 1.35, running on a Sun-3/280 under SunOS 3.5. I am building the documentation for TeXPS 2.19 (available by anonymous FTP from june.cs.washington.edu) and make usually dumps core with a SIGSEGV. It doesn't always happen, even though I have run make with identical starting conditions every time. When it does happen, it doesn't always happen in the same place in the Make code. The places where the SIGSEGV happens have been executed many times before the crash, without apparent error. Here is the most recent crash, one which I have seen several times: $ gdb make core GDB 3.2, Copyright (C) 1988 Free Software Foundation, Inc. There is ABSOLUTELY NO WARRANTY for GDB; type "info warranty" for details. GDB is free software and you are welcome to distribute copies of it under certain conditions; type "info copying" to see the conditions. Reading symbol data from /usr.MC68020/raptor1/contrib/src/TeXPS/TeXPS/doc/make.. .done. Core file is from "make". Program terminated with signal 11, Segmentation fault. Type "help" for a list of commands. (gdb) bt #0 0x1b458 in kill () #1 0x37ec in fatal_error_signal (...) (...) #2 0x185bc in _sigtramp () #3 0x4ae0 in file_impossible_p (...) (...) #4 0xc350 in pattern_search (...) (...) #5 0xbd52 in try_implicit_rule (...) (...) #6 0xa3da in update_file_1 (...) (...) #7 0x9e98 in update_file (...) (...) #8 0xaa00 in check_dep (...) (...) #9 0xa526 in update_file_1 (...) (...) #10 0x9e98 in update_file (...) (...) #11 0xaa00 in check_dep (...) (...) #12 0xa526 in update_file_1 (...) (...) #13 0x9e98 in update_file (...) (...) #14 0x9d68 in update_goal_chain (...) (...) #15 0x6f12 in main (...) (...) (gdb) fr 3 Reading in symbols for dir.c...done. #3 0x4ae0 in file_impossible_p (filename=(char *) 0x52b5c "SliTeX/SCCS/s.root.t ex") (dir.c line 295) 295 dir = find_directory (dirname); (gdb) p dir Reading in symbols for commands.c...done. $1 = (struct directory *) 0x22778 (gdb) list 290 else 291 { 292 char *dirname = (char *) alloca (dirend - filename + 1); 293 bcopy (p, dirname, dirend - p); 294 dirname[dirend - p] = '\0'; 295 dir = find_directory (dirname); 296 p = dirend + 1; 297 } 298 299 if (dir->files == 0) (gdb) p dirend $4 = (char *) 0x17 <Address 0x17 out of bounds> (gdb) p filename $5 = (char *) 0x5e918 "SliTeX/SCCS" (gdb) p rindex(filename, '/') Cannot invoke functions if the inferior is not running. (gdb) p dirname $6 = (char *) 0x4dd90 "" (gdb) p p $10 = (char *) 0x5e923 "" Notice the wildly incorrect value for dirend, which is the result of rindex(filename, '/'). The SIGSEGV happens on line 294, since bcopy is smart enough not to attempt a negative copy. I'm not sure what the alloca does, but it may be nasty. I get more or less the same results if I'm using Sun alloca, __builtin_alloca, or the C alloca from Emacs 18.54, so I don't think alloca is the problem as I did in an earlier version of this bug report. Here is the preprocessed source for dir.c, from which I have removed blank lines but nothing else. More information is available on request; I have no idea what to look for. -- Hal Peterson Domain: hrp@cray.com Cray Research Old style: hrp%cray.com@uc.msc.umn.edu 1440 Northland Dr. UUCP: uunet!cray!hrp Mendota Hts, MN 55120 USA Telephone: +1 612 681 3145 ======================================================================== # 1 "dir.c" # 1 "make.h" # 1 "/usr/include/signal.h" # 64 "/usr/include/signal.h" int (*signal())(); struct sigvec { int (*sv_handler)(); int sv_mask; int sv_flags; }; struct sigstack { char *ss_sp; int ss_onstack; }; struct sigcontext { int sc_onstack; int sc_mask; int sc_sp; int sc_pc; int sc_ps; }; # 18 "make.h" # 1 "/usr/include/stdio.h" extern struct _iobuf { int _cnt; unsigned char *_ptr; unsigned char *_base; int _bufsiz; short _flag; char _file; } _iob[]; extern struct _iobuf *fopen(); extern struct _iobuf *fdopen(); extern struct _iobuf *freopen(); extern struct _iobuf *popen(); extern struct _iobuf *tmpfile(); extern long ftell(); extern char *fgets(); extern char *gets(); extern char *ctermid(); extern char *cuserid(); extern char *tempnam(); extern char *tmpnam(); # 19 "make.h" # 1 "/usr/include/sys/param.h" # 1 "/usr/include/machine/param.h" # 90 "/usr/include/machine/param.h" # 12 "/usr/include/sys/param.h" # 1 "/usr/include/signal.h" # 157 "/usr/include/signal.h" # 62 "/usr/include/sys/param.h" # 1 "/usr/include/sys/types.h" # 1 "/usr/include/sys/sysmacros.h" # 10 "/usr/include/sys/types.h" typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; typedef unsigned short ushort; typedef unsigned int uint; typedef struct _physadr { short r[1]; } *physadr; typedef struct label_t { int val[13]; } label_t; typedef struct _quad { long val[2]; } quad; typedef long daddr_t; typedef char * caddr_t; typedef u_long ino_t; typedef long swblk_t; typedef int size_t; typedef long time_t; typedef short dev_t; typedef int off_t; typedef long key_t; typedef struct fd_set { int fds_bits[1]; } fd_set; # 114 "/usr/include/sys/param.h" # 25 "make.h" # 1 "/usr/include/sys/stat.h" struct stat { dev_t st_dev; ino_t st_ino; unsigned short st_mode; short st_nlink; short st_uid; short st_gid; dev_t st_rdev; off_t st_size; time_t st_atime; int st_spare1; time_t st_mtime; int st_spare2; time_t st_ctime; int st_spare3; long st_blksize; long st_blocks; long st_spare4[2]; }; # 30 "make.h" # 42 "make.h" # 1 "/usr/include/strings.h" char *strcat(); char *strncat(); int strcmp(); int strncmp(); char *strcpy(); char *strncpy(); int strlen(); char *index(); char *rindex(); # 43 "make.h" extern int bcmp (); extern void bzero (), bcopy (); extern void die (); extern void fatal (), error (); extern void pfatal_with_name (), perror_with_name (); extern char *savestring (), *concat (); extern char *xmalloc (), *xrealloc (); extern char *find_next_token (), *next_token (), *end_of_token (); extern void collapse_continuations (), collapse_line (); extern char *sindex (), *lindex (); extern int alpha_compare (); extern void print_spaces (); extern struct dep *copy_dep_chain (); extern char *find_percent (); extern int ar_name (); extern int ar_touch (); extern time_t ar_member_date (); extern void dir_load (); extern int dir_file_exists_p (), file_exists_p (), file_impossible_p (); extern void file_impossible (); extern char *dir_name (); extern void set_default_suffixes (), install_default_implicit_rules (); extern void convert_to_pattern (), count_implicit_rule_limits (); extern void create_pattern_rule (); extern void build_vpath_lists (), construct_vpath_list (); extern int vpath_search (); extern void construct_include_path (); extern int update_goal_chain (); extern int notice_finished_file (); extern int glob_pattern_p (); extern char **glob_filename (); extern void free (); extern void abort (); extern int unlink (), stat (), execvp (); extern void qsort (); extern int atoi (); extern char *getwd (); extern char *reading_filename; extern unsigned int *reading_lineno_ptr; extern int just_print_flag, silent_flag, ignore_errors_flag, keep_going_flag; extern int debug_flag, print_data_base_flag, question_flag, touch_flag; extern int env_overrides, no_builtin_rules_flag, print_version_flag; extern int print_directory_flag; extern unsigned int job_slots; extern double max_load_average; extern char *program; extern unsigned int makelevel; # 18 "dir.c" # 1 "/usr/include/sys/dir.h" struct direct { u_long d_fileno; u_short d_reclen; u_short d_namlen; char d_name[255 + 1]; }; typedef struct _dirdesc { int dd_fd; long dd_loc; long dd_size; long dd_bbase; long dd_entno; long dd_bsize; char *dd_buf; } DIR; extern DIR *opendir(); extern struct direct *readdir(); extern long telldir(); extern void seekdir(); extern void closedir(); # 29 "dir.c" struct directory { struct directory *next; char *name; struct dirfile **files; DIR *dirstream; }; static struct directory *directories[23 ]; static unsigned int open_directories = 0; struct dirfile { struct dirfile *next; char *name; char impossible; }; static struct directory * find_directory (name) register char *name; { register unsigned int hash = 0; register char *p; register struct directory *dir; for (p = name; *p != '\0'; ++p) { hash += *p; hash = (hash << 7) + (hash >> 20); } hash %= 23 ; for (dir = directories[hash]; dir != 0; dir = dir->next) if (((dir->name) == ( name) || (*(dir->name) == *( name) && (*(dir->name) == '\0' || !strcmp ((dir->name) + 1, ( name) + 1)))) ) break; if (dir == 0) { struct stat st; dir = (struct directory *) xmalloc (sizeof (struct directory)); dir->next = directories[hash]; directories[hash] = dir; dir->name = savestring (name, p - name); dir->dirstream = opendir (name); if (dir->dirstream == 0) dir->files = 0; else { dir->files = (struct dirfile **) xmalloc (sizeof (struct dirfile) * 1007 ); bzero ((char *) dir->files, sizeof (struct dirfile) * 1007 ); ++open_directories; if (open_directories == 10 ) (void) dir_file_exists_p (dir->name, ""); } } return dir; } int dir_file_exists_p (dirname, filename) register char *dirname; register char *filename; { register unsigned int hash; register char *p; register struct directory *dir; register struct dirfile *df; register struct direct *d; dir = find_directory (dirname); if (dir->files == 0) return 0; if (*filename == '\0') return 1; hash = 0; for (p = filename; *p != '\0'; ++p) { hash += *p; hash = (hash << 7) + (hash >> 20); } hash %= 1007 ; for (df = dir->files[hash]; df != 0; df = df->next) if (((df->name) == ( filename) || (*(df->name) == *( filename) && (*(df->name) == '\0' || !strcmp ((df->name) + 1, ( filename) + 1)))) ) return !df->impossible; if (dir->dirstream == 0) return 0; while ((d = readdir (dir->dirstream)) != 0) { register unsigned int newhash = 0; register unsigned int i; for (i = 0; i < ((d)->d_namlen) ; ++i) { newhash += d->d_name[i]; newhash = (newhash << 7) + (newhash >> 20); } newhash %= 1007 ; df = (struct dirfile *) xmalloc (sizeof (struct dirfile)); df->next = dir->files[newhash]; dir->files[newhash] = df; df->name = savestring (d->d_name, ((d)->d_namlen) ); df->impossible = 0; if (newhash == hash && ((d->d_name) == ( filename) || (*(d->d_name) == *( filename) && (*(d->d_name) == '\0' || !strcmp ((d->d_name) + 1, ( filename) + 1)))) ) return 1; } if (d == 0) { --open_directories; closedir (dir->dirstream); dir->dirstream = 0; } return 0; } int file_exists_p (name) register char *name; { char *dirend; char *dirname; if (ar_name (name)) return ar_member_date (name) != (time_t) -1; dirend = rindex (name, '/'); if (dirend == 0) return dir_file_exists_p (".", name); dirname = (char *) alloca (dirend - name + 1); bcopy (name, dirname, dirend - name); dirname[dirend - name] = '\0'; return dir_file_exists_p (dirname, dirend + 1); } void file_impossible (filename) register char *filename; { char *dirend; register char *p = filename; register unsigned int hash; register struct directory *dir; register struct dirfile *new; dirend = rindex (p, '/'); if (dirend == 0) dir = find_directory ("."); else { char *dirname = (char *) alloca (dirend - p + 1); bcopy (p, dirname, dirend - p); dirname[dirend - p] = '\0'; dir = find_directory (dirname); filename = p = dirend + 1; } hash = 0; while (*p != '\0') { hash += *p++; hash = (hash << 7) + (hash >> 20); } hash %= 1007 ; if (dir->files == 0) { dir->files = (struct dirfile **) xmalloc (sizeof (struct dirfile) * 1007 ); bzero ((char *) dir->files, sizeof (struct dirfile) * 1007 ); } new = (struct dirfile *) xmalloc (sizeof (struct dirfile)); new->next = dir->files[hash]; dir->files[hash] = new; new->name = savestring (filename, strlen (filename)); new->impossible = 1; } int file_impossible_p (filename) char *filename; { char *dirend; register char *p = filename; register unsigned int hash; register struct directory *dir; register struct dirfile *next; dirend = rindex (filename, '/'); if (dirend == 0) dir = find_directory ("."); else { char *dirname = (char *) alloca (dirend - filename + 1); bcopy (p, dirname, dirend - p); dirname[dirend - p] = '\0'; dir = find_directory (dirname); p = dirend + 1; } if (dir->files == 0) return 0; hash = 0; while (*p != '\0') { hash += *p++; hash = (hash << 7) + (hash >> 20); } hash %= 1007 ; for (next = dir->files[hash]; next != 0; next = next->next) if (((filename) == ( next->name) || (*(filename) == *( next->name) && (*(filename) == '\0' || !strcmp ((filename) + 1, ( next->name) + 1)))) ) return next->impossible; return 0; } char * dir_name (dir) char *dir; { return find_directory (dir)->name; } void print_dir_data_base () { register unsigned int i, dirs, files, impossible; register struct directory *dir; puts ("\n# Directories\n"); dirs = files = impossible = 0; for (i = 0; i < 23 ; ++i) for (dir = directories[i]; dir != 0; dir = dir->next) { ++dirs; if (dir->files == 0) printf ("# %s: could not be opened.\n", dir->name); else { register unsigned int f = 0, im = 0; register unsigned int j; register struct dirfile *df; for (j = 0; j < 1007 ; ++j) for (df = dir->files[j]; df != 0; df = df->next) if (df->impossible) ++im; else ++f; printf ("# %s: ", dir->name); if (f == 0) fputs ("No", (&_iob[1]) ); else printf ("%u", f); fputs (" files, ", (&_iob[1]) ); if (im == 0) fputs ("no", (&_iob[1]) ); else printf ("%u", im); fputs (" impossibilities", (&_iob[1]) ); if (dir->dirstream == 0) puts ("."); else puts (" so far."); files += f; impossible += im; } } fputs ("\n# ", (&_iob[1]) ); if (files == 0) fputs ("No", (&_iob[1]) ); else printf ("%u", files); fputs (" files, ", (&_iob[1]) ); if (impossible == 0) fputs ("no", (&_iob[1]) ); else printf ("%u", impossible); printf (" impossibilities in %u directories.\n", dirs); }