[Message Prev][Message Next][Thread Prev][Thread Next][Message Index][Thread Index]

[MD:2826]Portable dumper



# 林さんの code が面白くて眠れない……
# 朝になってしまった

At 17 Jan 2002 20:00:21 +0900,
Yoshiki Hayashi wrote:
> pdump_relocate_objects に bug があって、mmap の返り値によっ
> て動いたり動かなかったりすることが判明しました。
> 
> 永野君の buffer local があやしいかも、というのはあたりで、
> relocate を忘れているのがありました。後、PDUMP_OFFSET を 0
> や 12288 にして MAP_FIXED でむりやりその場所に mmap した場合
> に正しく動かない、という現象があるので、後で debug します。

この修正で、僕の手元でも garbage-collect が動くようになりました!!

ただ、また新たな bug を見つけました。-q -no-site-file で起動して
*scratch* buffer で (category-table) を評価すると、100% SEGV が飛んで
きます。-f category-table では落ちません。backtrace (bt1.txt) が示す通
り、PVEC_CHAR_TABLE を print() しようとして死んでいます。

また、同じような症状で、立ち上げた Emacs 上で M-x garbage-collect を数
回繰り返すと落ちます (bt2.txt)。これは GC で落ちているのではなく、
garbage-collect という symbol の oblookup に失敗しています。こちらは、
何回やれば落ちるのか、といったようなきちんとした再現性を、まだ見付けて
いません。

これらから、何となく、Vectorlike まわりにまだ bug があるのではないかと
いう気がしています。

これだけではなんなので、emacs.dmp を探す code を (XEmacs から丸ごとぱ
くってきて) でっちあげました。林さんの patch 3つのあとにあてて下さい。
注意ですが、この patch をあてると src に移動しなくても起動できるように
なるのですが、起動時の argv[0] を見ているので、emacs 以外では 
emacs.dmp を見付けられず、起動できなくなります。つまり、今は temacs や 
emacs-20.7.* が使えません。(これどうしましょうか。dump 先の file 名を
ちゃんと決めるのが先かな) なお、林さんの2つ目の patch をあてた時点で、
生成される emacs, emacs-20.7.* は temacs と全く同じものになっています。

なお、添付する2つの backtrace は、両方とも僕の patch を当てて作った 
binary から吐かせたものですが、これを当てる前から同じ症状が出ていまし
た。

-- 
Keiichiro Nagano
Program received signal SIGSEGV, Segmentation fault.
0x08102b7f in print (obj=1074982156, printcharfun=269224088, escapeflag=1)
    at print.c:1578
1578                  c = XBOOL_VECTOR (obj)->data[i];
(gdb) bt
#0  0x08102b7f in print (obj=1074982156, printcharfun=269224088, escapeflag=1)
    at print.c:1578
#1  0x08102fbc in print (obj=1074980588, printcharfun=269224088, escapeflag=1)
    at print.c:1683
#2  0x08100c89 in Fprin1 (object=1074980588, printcharfun=269224088)
    at print.c:860
#3  0x080f61d2 in Ffuncall (nargs=2, args=0x7ffff0e0) at eval.c:2476
#4  0x08120c01 in Fbyte_code (bytestr=805698120, vector=1074773472, maxdepth=9)
    at bytecode.c:433
#5  0x080f673a in funcall_lambda (fun=1074773440, nargs=1,
    arg_vector=0x7ffff234) at eval.c:2660
#6  0x080f62a5 in Ffuncall (nargs=2, args=0x7ffff230) at eval.c:2521
#7  0x08120c01 in Fbyte_code (bytestr=805697964, vector=1074773416, maxdepth=2)
    at bytecode.c:433
#8  0x080f673a in funcall_lambda (fun=1074773384, nargs=0,
    arg_vector=0x7ffff384) at eval.c:2660
#9  0x080f62a5 in Ffuncall (nargs=1, args=0x7ffff380) at eval.c:2521
#10 0x080f5d7e in apply1 (fn=269280776, arg=269224088) at eval.c:2226
#11 0x080f1994 in Fcall_interactively (function=269280776,
    record_flag=269224088, keys=1074958992) at callint.c:360
#12 0x080a2d1a in Fcommand_execute (cmd=269280776, record_flag=269224088,
    keys=269224088, special=269224088) at keyboard.c:7984
#13 0x0809aef0 in command_loop_1 () at keyboard.c:1502
#14 0x080f43ea in internal_condition_case (bfun=0x809a280 <command_loop_1>,
    handlers=269230616, hfun=0x8099ef0 <cmd_error>) at eval.c:1156
#15 0x0809a148 in command_loop_2 () at keyboard.c:1093
#16 0x080f3f5a in internal_catch (tag=269270504,
    func=0x809a120 <command_loop_2>, arg=269224088) at eval.c:931
#17 0x0809a0f3 in command_loop () at keyboard.c:1072
#18 0x08099cfe in recursive_edit_1 () at keyboard.c:821
#19 0x08099dfc in Frecursive_edit () at keyboard.c:869
#20 0x08098e7a in main (argc=3, argv=0x7ffffa24, envp=0x7ffffa34)
    at emacs.c:1452
#21 0x2aca79ae in __libc_start_main (main=0x8098260 <main>, argc=3,
    argv=0x7ffffa24, init=0x804c710 <_init>, fini=0x8131eb0 <_fini>,
    rtld_fini=0x2aab66f4 <_dl_fini>, stack_end=0x7ffffa1c)
    at ../sysdeps/generic/libc-start.c:92
(gdb) p obj
$11 = 1074982156
(gdb) xtype
Lisp_Vectorlike
PVEC_BOOL_VECTOR
(gdb) p obj
$12 = 1074982156
(gdb) xvector
$13 = (struct Lisp_Vector *) 0x12ed0c
0
(gdb) p obj
$14 = 1074982156
(gdb) xboolvector
$15 = (struct Lisp_Bool_Vector *) 0x12ed0c
0
(gdb) up
#1  0x08102fbc in print (obj=1074980588, printcharfun=269224088, escapeflag=1)
    at print.c:1683
1683                    print (tem, printcharfun, escapeflag);
(gdb) p obj
$16 = 1074980588
(gdb) xtype
Lisp_Vectorlike
PVEC_CHAR_TABLE
(gdb) p obj
$17 = 1074980588
(gdb) xvector
$18 = (struct Lisp_Vector *) 0x12e6ec
0
(gdb) p obj
$19 = 1074980588
(gdb) xchartable
$20 = (struct Lisp_Char_Table *) 0x12e6ec
Purpose: This context has class, union or enum Lisp_Symbol, not a struct.
(gdb) up
#2  0x08100c89 in Fprin1 (object=1074980588, printcharfun=269224088)
    at print.c:860
860       print (object, printcharfun, 1);
(gdb) p object
$21 = 1074980588
(gdb) xtype
Lisp_Vectorlike
PVEC_CHAR_TABLE
(gdb) p object
$22 = 1074980588
(gdb) xvector
$23 = (struct Lisp_Vector *) 0x12e6ec
0
(gdb) p object
$24 = 1074980588
(gdb) xchartable
$25 = (struct Lisp_Char_Table *) 0x12e6ec
Purpose: This context has class, union or enum Lisp_Symbol, not a struct.

(gdb) bt
#0  0x2acae791 in __kill () from /lib/libc.so.6
#1  0x08097c34 in fatal_error_signal (sig=11) at emacs.c:254
#2  <signal handler called>
#3  0x0810766f in oblookup (obarray=1218018696, ptr=0xaf014 "garbage-collect",
    size=15, size_byte=15) at lread.c:2736
#4  0x081073c9 in Fintern_soft (string=806023176, obarray=1218018696)
    at lread.c:2619
#5  0x080f61d2 in Ffuncall (nargs=3, args=0x7fffe910) at eval.c:2476
#6  0x08120c01 in Fbyte_code (bytestr=949369544, vector=1217795584, maxdepth=3)
    at bytecode.c:433
#7  0x080f673a in funcall_lambda (fun=1217795664, nargs=0,
    arg_vector=0x7fffea44) at eval.c:2660
#8  0x080f62a5 in Ffuncall (nargs=1, args=0x7fffea40) at eval.c:2521
#9  0x08120c01 in Fbyte_code (bytestr=949369640, vector=1217795792, maxdepth=2)
    at bytecode.c:433
#10 0x080f673a in funcall_lambda (fun=1217795872, nargs=0,
    arg_vector=0x7fffec28) at eval.c:2660
#11 0x080f62a5 in Ffuncall (nargs=1, args=0x7fffec24) at eval.c:2521
#12 0x080f57b8 in Fapply (nargs=2, args=0x7fffec24) at eval.c:1932
#13 0x080f60f4 in Ffuncall (nargs=3, args=0x7fffec20) at eval.c:2454
#14 0x08120c01 in Fbyte_code (bytestr=949366696, vector=1217054896, maxdepth=4)
    at bytecode.c:433
#15 0x080f5506 in Feval (form=1486160036) at eval.c:1837
#16 0x080f42e9 in Fcondition_case (args=1484997836) at eval.c:1105
#17 0x081212c2 in Fbyte_code (bytestr=949366576, vector=1216711032, maxdepth=5)
    at bytecode.c:606
#18 0x080f673a in funcall_lambda (fun=1216711168, nargs=1,
    arg_vector=0x7fffefe4) at eval.c:2660
#19 0x080f62a5 in Ffuncall (nargs=2, args=0x7fffefe0) at eval.c:2521
#20 0x080f5e20 in call1 (fn=269279576, arg1=1218025000) at eval.c:2270
#21 0x0809d897 in timer_check (do_it_now=1) at keyboard.c:3481
#22 0x0809c9ea in readable_events (do_timers_now=1) at keyboard.c:2719
#23 0x0809f0ca in get_input_pending (addr=0x8817758, do_timers_now=1)
    at keyboard.c:5250
#24 0x080a32c5 in detect_input_pending_run_timers (do_display=1)
    at keyboard.c:8199
#25 0x0812554e in wait_reading_process_input (time_limit=30, microsecs=0,
    read_kbd=268435455, do_display=1) at process.c:2567
#26 0x08051175 in sit_for (sec=30, usec=0, reading=1, display=1,
    initial_display=0) at dispnew.c:2452
#27 0x0809bb25 in read_char (commandflag=1, nmaps=2, maps=0x7ffff450,
    prev_event=269224088, used_mouse_menu=0x7ffff508) at keyboard.c:2124
#28 0x080a1488 in read_key_sequence (keybuf=0x7ffff590, bufsize=30,
    prompt=269224088, dont_downcase_last=0, can_return_switch_frame=1,
    fix_current_buffer=1) at keyboard.c:7023
#29 0x0809a56b in command_loop_1 () at keyboard.c:1275
#30 0x080f43ea in internal_condition_case (bfun=0x809a280 <command_loop_1>,
    handlers=269230616, hfun=0x8099ef0 <cmd_error>) at eval.c:1156
#31 0x0809a148 in command_loop_2 () at keyboard.c:1093
#32 0x080f3f5a in internal_catch (tag=269270504,
    func=0x809a120 <command_loop_2>, arg=269224088) at eval.c:931
---Type <return> to continue, or q <return> to quit---
#33 0x0809a0f3 in command_loop () at keyboard.c:1072
#34 0x08099cfe in recursive_edit_1 () at keyboard.c:821
#35 0x08099dfc in Frecursive_edit () at keyboard.c:869
#36 0x08098e7a in main (argc=1, argv=0x7ffffa84, envp=0x7ffffa8c)
    at emacs.c:1452
#37 0x2aca79ae in __libc_start_main (main=0x8098260 <main>, argc=1,
    argv=0x7ffffa84, init=0x804c710 <_init>, fini=0x8131eb0 <_fini>,
    rtld_fini=0x2aab66f4 <_dl_fini>, stack_end=0x7ffffa7c)
    at ../sysdeps/generic/libc-start.c:92
(gdb) frame 3
#3  0x0810766f in oblookup (obarray=1218018696, ptr=0xaf014 "garbage-collect",
    size=15, size_byte=15) at lread.c:2736
2736            if (STRING_BYTES (XSYMBOL (tail)->name) == size_byte)
(gdb) p obarray
$1 = 1218018696
(gdb) xtype
Lisp_Vectorlike
PVEC_NORMAL_VECTOR
(gdb) p obarray
$2 = 1218018696
(gdb) xvector
$3 = (struct Lisp_Vector *) 0x8997d88
{412714276, 412714132, 411552588, 411552564, 412713628, 412713164, 412713748,
  411552444, 412713700, 412713044, 412714324, 0, 412714420, 412714348,
  412714156, 412714060, 412714300, 411552516, 412713212, 411552492, 411552540,
  412714372, 412712564, 412713404, 412714204, 412714468, 411552420, 412713092,
  412713308, 412714444, 412713260}

diff -ur 020118-2-pdump/src/alloc.c pdump/src/alloc.c
--- src/alloc.c	Fri Jan 18 00:20:23 2002
+++ src/alloc.c	Fri Jan 18 06:53:02 2002
@@ -3697,20 +3697,25 @@
 }									\
 while (0)
 
+static int pdump_open_dumped_file (char *argv0);
 static void pdump_relocate_objects (long offset);
 int
-pdump_load ()
+pdump_load (char *argv0)
 {
   int i;
-  int fd = open ("emacs.dmp", O_RDONLY);
+  int fd;
   char *ret;
   long offset;
 
+  if ((fd = pdump_open_dumped_file (argv0)) < 0)
+    return 1;
+
   read (fd, &pdump_header, sizeof (pdump_header));
   lseek (fd, 0, SEEK_SET);
   ret = (char *)mmap (pdump_header.offset, pdump_header.objects_size
 		      + sizeof (pdump_header_t),
 		      PROT_READ|PROT_WRITE, MAP_PRIVATE,
+
 		      fd, 0);
   if ((long) ret == -1)
     return 1;
@@ -3956,7 +3961,8 @@
 	case Lisp_Misc_Buffer_Local_Value:
 	case Lisp_Misc_Some_Buffer_Local_Value:
 	  {
-	    struct Lisp_Buffer_Local_Value *ptr = (struct Lisp_Buffer_Local_Value *)obj_ptr;
+	    struct Lisp_Buffer_Local_Value *ptr =
+	      (struct Lisp_Buffer_Local_Value *)obj_ptr;
 	    PDUMP_RELOCATE (ptr->buffer, offset);
 	    PDUMP_RELOCATE (ptr->frame, offset);
 	    PDUMP_RELOCATE (ptr->realvalue, offset);
@@ -4059,6 +4065,152 @@
 }
 
 
+/* dumped file search */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* FIXME: this should be marged with emacs.c */
+#ifndef SEPCHAR
+#define SEPCHAR ':'
+#endif
+
+static int
+pdump_file_check_readable (char *filename)
+{
+  struct stat stat_buf;
+  /* fprintf(stderr, "trying dumped file %s...\n", filename); */
+  if (stat (filename, &stat_buf) == 0)
+    if ((stat_buf.st_mode & S_IRUSR) != 0)
+      {
+	/* fprintf(stderr, "trying dumped file %s... ok\n", filename); */
+	return 1;
+      }
+  /* fprintf(stderr, "trying dumped file %s... ng\n", filename); */
+  return 0;
+}
+
+static int
+pdump_find_exe_path (char *argv0, char *exe_path)
+{
+#ifdef WINDOWSNT
+  GetModuleFileName (NULL, exe_path, PATH_MAX);
+#else /* !WINDOWSNT */
+  char *w;
+  const char *dir, *p;
+
+  dir = argv0;
+  if (dir[0] == '-')
+    {
+      /* Emacs as a login shell, how religious! */
+      dir = getenv ("SHELL");
+    }
+
+  p = dir + strlen (dir);
+  while (p != dir && !IS_ANY_SEP (p[-1])) p--;
+
+  if (p != dir)
+    {
+      /* invocation-name includes a directory component -- presumably it
+	 is relative to cwd, not $PATH */
+      strcpy (exe_path, dir);
+    }
+  else
+    {
+      const char *path = getenv ("PATH");
+      const char *name = p;
+      for (;;)
+	{
+	  p = path;
+	  while (*p && *p != SEPCHAR)
+	    p++;
+	  if (p == path)
+	    {
+	      exe_path[0] = '.';
+	      w = exe_path + 1;
+	    }
+	  else
+	    {
+	      memcpy (exe_path, path, p - path);
+	      w = exe_path + (p - path);
+	    }
+	  if (!IS_DIRECTORY_SEP (w[-1]))
+	    {
+	      *w++ = '/';
+	    }
+	  strcpy (w, name);
+
+	  /* ### #$%$#^$^@%$^#%@$ ! */
+#ifdef access
+#undef access
+#endif
+
+	  if (!access (exe_path, X_OK))
+	    break;
+	  if (!*p)
+	    {
+	      /* Oh well, let's have some kind of default */
+	      sprintf (exe_path, "./%s", name);
+	      break;
+	    }
+	  path = p+1;
+	}
+    }
+#endif /* WINDOWSNT */
+
+  return 1;
+}
+
+static int
+pdump_find_dumped_file (char *exe_path)
+{
+  char *w = exe_path + strlen (exe_path);
+
+  do
+    {
+      /* ### FIXME: the versioning and dump_id are not implemented yet */
+#if 0
+      sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
+      if (pdump_file_check_readable (exe_path))
+	return 1;
+
+      sprintf (w, "-%08x.dmp", dump_id);
+      if (pdump_file_check_readable (exe_path))
+	return 1;
+
+#endif
+      sprintf (w, ".dmp");
+      if (pdump_file_check_readable (exe_path))
+	return 1;
+
+      do
+	w--;
+      while (w > exe_path
+	     && !IS_DIRECTORY_SEP (*w)
+	     && (*w != '-')
+	     && (*w != '.'));
+    }
+  while (w > exe_path && !IS_DIRECTORY_SEP (*w));
+
+  /* ### FIXME: temporal logic; try to find fixed name `emacs.dmp' */
+  sprintf (w+1, "emacs.dmp");
+  if (pdump_file_check_readable (exe_path))
+    return 1;
+
+  return 0;
+}
+
+static int
+pdump_open_dumped_file (char *argv0)
+{
+  char path[PATH_MAX];
+  if (pdump_find_exe_path (argv0, path))
+    if (pdump_find_dumped_file (path))
+      return open(path, O_RDONLY);
+  return -1;
+}
+
+
 /* Initialization */
 
 void
diff -ur 020118-2-pdump/src/emacs.c pdump/src/emacs.c
--- src/emacs.c	Fri Jan 18 00:20:23 2002
+++ src/emacs.c	Fri Jan 18 03:06:35 2002
@@ -1017,7 +1017,7 @@
 #ifdef PDUMP
   else
     {
-      if (pdump_load ())
+      if (pdump_load (argv[0]))
 	{
 	  fprintf (stderr, "emacs: failed to load dumped file\n");
 	  exit (1);