#include <config.h>
#include "lisp.h"
-#include "dump-id.h"
#include "specifier.h"
#include "elhash.h"
#include "sysfile.h"
#include "console-stream.h"
#include "dumper.h"
+#include "sysdep.h"
#ifdef WIN32_NATIVE
#include "nt.h"
static void (*pdump_free) (void);
-static const unsigned char pdump_align_table[256] =
+static unsigned char pdump_align_table[] =
{
- 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+ 64, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
+ 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
+ 32, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1,
+ 16, 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1
};
-typedef struct pdump_entry_list_elmt
+static inline unsigned int
+pdump_size_to_align (size_t size)
{
- struct pdump_entry_list_elmt *next;
+ return pdump_align_table[size % countof (pdump_align_table)];
+}
+
+typedef struct pdump_entry_list_elt
+{
+ struct pdump_entry_list_elt *next;
const void *obj;
size_t size;
int count;
EMACS_INT save_offset;
-} pdump_entry_list_elmt;
+} pdump_entry_list_elt;
typedef struct
{
- pdump_entry_list_elmt *first;
+ pdump_entry_list_elt *first;
int align;
int count;
} pdump_entry_list;
-typedef struct pdump_struct_list_elmt
+typedef struct pdump_struct_list_elt
{
pdump_entry_list list;
const struct struct_description *sdesc;
-} pdump_struct_list_elmt;
+} pdump_struct_list_elt;
typedef struct
{
- pdump_struct_list_elmt *list;
+ pdump_struct_list_elt *list;
int count;
int size;
} pdump_struct_list;
-static pdump_entry_list pdump_object_table[256];
+static pdump_entry_list *pdump_object_table;
static pdump_entry_list pdump_opaque_data_list;
static pdump_struct_list pdump_struct_table;
-static int pdump_alert_undump_object[256];
+static int *pdump_alert_undump_object;
static unsigned long cur_offset;
static size_t max_size;
static void *pdump_buf;
static FILE *pdump_out;
+#ifdef UTF2000
+#define PDUMP_HASHSIZE 20000001
+#else
#define PDUMP_HASHSIZE 200001
+#endif
-static pdump_entry_list_elmt **pdump_hash;
+static pdump_entry_list_elt **pdump_hash;
/* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
static int
return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
}
-static pdump_entry_list_elmt *
+static pdump_entry_list_elt *
pdump_get_entry (const void *obj)
{
int pos = pdump_make_hash (obj);
- pdump_entry_list_elmt *e;
+ pdump_entry_list_elt *e;
assert (obj != 0);
pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size,
int count)
{
- pdump_entry_list_elmt *e;
- int align;
+ pdump_entry_list_elt *e;
int pos = pdump_make_hash (obj);
while ((e = pdump_hash[pos]) != 0)
pos = 0;
}
- e = xnew (pdump_entry_list_elmt);
+ e = xnew (pdump_entry_list_elt);
e->next = list->first;
e->obj = obj;
list->count += count;
pdump_hash[pos] = e;
- align = pdump_align_table[size & 255];
+ {
+ int align = pdump_size_to_align (size);
- if (align < list->align)
- list->align = align;
+ if (align < list->align)
+ list->align = align;
+ }
}
static pdump_entry_list *
pdump_struct_table.size = 10;
else
pdump_struct_table.size = pdump_struct_table.size * 2;
- pdump_struct_table.list = (pdump_struct_list_elmt *)
+ pdump_struct_table.list = (pdump_struct_list_elt *)
xrealloc (pdump_struct_table.list,
- pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
+ pdump_struct_table.size * sizeof (pdump_struct_list_elt));
}
pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
- pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
+ pdump_struct_table.list[pdump_struct_table.count].list.align = ALIGNOF (max_align_t);
pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
else
{
stderr_out (" - %s (%d, %d)\n",
- LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
- backtrace[i].position,
- backtrace[i].offset);
+ LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
+ backtrace[i].position,
+ backtrace[i].offset);
}
}
}
const struct lrecord_description *idesc,
const void *idata)
{
- EMACS_INT count;
+ EMACS_INT count = 0; /* initialize to shut up GCC */
const void *irdata;
int line = XD_INDIRECT_VAL (code);
stderr_out ("Unsupported count type : %d (line = %d, code=%ld)\n",
idesc[line].type, line, (long)code);
pdump_backtrace ();
- abort ();
+ ABORT ();
}
count += delta;
return count;
default:
stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
pdump_backtrace ();
- abort ();
+ ABORT ();
};
}
}
if (imp->description)
{
int me = depth++;
- if (me>65536)
+ if (me>=65536)
{
stderr_out ("Backtrace overflow, loop ?\n");
- abort ();
+ ABORT ();
}
backtrace[me].obj = objh;
backtrace[me].position = 0;
{
int me = depth++;
int i;
- if (me>65536)
+ if (me>=65536)
{
stderr_out ("Backtrace overflow, loop ?\n");
- abort ();
+ ABORT ();
}
backtrace[me].obj = 0;
backtrace[me].position = 0;
}
static void
-pdump_dump_data (pdump_entry_list_elmt *elmt,
+pdump_dump_data (pdump_entry_list_elt *elt,
const struct lrecord_description *desc)
{
- size_t size = elmt->size;
- int count = elmt->count;
+ size_t size = elt->size;
+ int count = elt->count;
if (desc)
{
int pos, i;
- memcpy (pdump_buf, elmt->obj, size*count);
+ memcpy (pdump_buf, elt->obj, size*count);
for (i=0; i<count; i++)
{
switch (desc[pos].type)
{
case XD_SPECIFIER_END:
- desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
+ desc = ((const Lisp_Specifier *)(elt->obj))->methods->extra_description;
goto restart;
case XD_SIZE_T:
case XD_INT:
{
EMACS_INT val = desc[pos].data1;
if (XD_IS_INDIRECT (val))
- val = pdump_get_indirect_count (val, desc, elmt->obj);
+ val = pdump_get_indirect_count (val, desc, elt->obj);
*(int *)rdata = val;
break;
}
case XD_LO_LINK:
{
Lisp_Object obj = *(Lisp_Object *)rdata;
- pdump_entry_list_elmt *elmt1;
+ pdump_entry_list_elt *elt1;
for (;;)
{
- elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
- if (elmt1)
+ elt1 = pdump_get_entry (XRECORD_LHEADER (obj));
+ if (elt1)
break;
obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
}
- *(EMACS_INT *)rdata = elmt1->save_offset;
+ *(EMACS_INT *)rdata = elt1->save_offset;
break;
}
case XD_LISP_OBJECT:
EMACS_INT num = desc[pos].data1;
int j;
if (XD_IS_INDIRECT (num))
- num = pdump_get_indirect_count (num, desc, elmt->obj);
+ num = pdump_get_indirect_count (num, desc, elt->obj);
for (j=0; j<num; j++)
{
}
default:
stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
- abort ();
+ ABORT ();
}
}
}
}
- fwrite (desc ? pdump_buf : elmt->obj, size, count, pdump_out);
+ fwrite (desc ? pdump_buf : elt->obj, size, count, pdump_out);
}
static void
}
default:
stderr_out ("Unsupported dump type : %d\n", desc[pos].type);
- abort ();
+ ABORT ();
};
}
}
static void
-pdump_allocate_offset (pdump_entry_list_elmt *elmt,
+pdump_allocate_offset (pdump_entry_list_elt *elt,
const struct lrecord_description *desc)
{
- size_t size = elmt->count * elmt->size;
- elmt->save_offset = cur_offset;
+ size_t size = elt->count * elt->size;
+ elt->save_offset = cur_offset;
if (size>max_size)
max_size = size;
cur_offset += size;
}
static void
-pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *,
+pdump_scan_by_alignment (void (*f)(pdump_entry_list_elt *,
const struct lrecord_description *))
{
- int align, i;
- const struct lrecord_description *idesc;
- pdump_entry_list_elmt *elmt;
- for (align=8; align>=0; align--)
+ int align;
+
+ for (align = ALIGNOF (max_align_t); align; align>>=1)
{
+ size_t i;
+ pdump_entry_list_elt *elt;
+
for (i=0; i<lrecord_type_count; i++)
if (pdump_object_table[i].align == align)
- {
- elmt = pdump_object_table[i].first;
- if (!elmt)
- continue;
- idesc = lrecord_implementations_table[i]->description;
- while (elmt)
- {
- f (elmt, idesc);
- elmt = elmt->next;
- }
- }
+ for (elt = pdump_object_table[i].first; elt; elt = elt->next)
+ f (elt, lrecord_implementations_table[i]->description);
for (i=0; i<pdump_struct_table.count; i++)
- if (pdump_struct_table.list[i].list.align == align)
- {
- elmt = pdump_struct_table.list[i].list.first;
- idesc = pdump_struct_table.list[i].sdesc->description;
- while (elmt)
- {
- f (elmt, idesc);
- elmt = elmt->next;
- }
- }
-
- elmt = pdump_opaque_data_list.first;
- while (elmt)
{
- if (pdump_align_table[elmt->size & 255] == align)
- f (elmt, 0);
- elmt = elmt->next;
+ pdump_struct_list_elt list = pdump_struct_table.list[i];
+ if (list.list.align == align)
+ for (elt = list.list.first; elt; elt = elt->next)
+ f (elt, list.sdesc->description);
}
+
+ for (elt = pdump_opaque_data_list.first; elt; elt = elt->next)
+ if (pdump_size_to_align (elt->size) == align)
+ f (elt, 0);
}
}
static void
pdump_dump_root_struct_ptrs (void)
{
- int i;
+ size_t i;
size_t count = Dynarr_length (pdump_root_struct_ptrs);
pdump_static_pointer *data = alloca_array (pdump_static_pointer, count);
for (i = 0; i < count; i++)
static void
pdump_dump_rtables (void)
{
- int i;
- pdump_entry_list_elmt *elmt;
+ size_t i;
+ pdump_entry_list_elt *elt;
pdump_reloc_table rt;
for (i=0; i<lrecord_type_count; i++)
{
- elmt = pdump_object_table[i].first;
- if (!elmt)
+ elt = pdump_object_table[i].first;
+ if (!elt)
continue;
rt.desc = lrecord_implementations_table[i]->description;
rt.count = pdump_object_table[i].count;
PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
- while (elmt)
+ while (elt)
{
- EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
+ EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
- elmt = elmt->next;
+ elt = elt->next;
}
}
for (i=0; i<pdump_struct_table.count; i++)
{
- elmt = pdump_struct_table.list[i].list.first;
+ elt = pdump_struct_table.list[i].list.first;
rt.desc = pdump_struct_table.list[i].sdesc->description;
rt.count = pdump_struct_table.list[i].list.count;
PDUMP_WRITE_ALIGNED (pdump_reloc_table, rt);
- while (elmt)
+ while (elt)
{
- EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
+ EMACS_INT rdata = pdump_get_entry (elt->obj)->save_offset;
int j;
- for (j=0; j<elmt->count; j++)
+ for (j=0; j<elt->count; j++)
{
PDUMP_WRITE_ALIGNED (EMACS_INT, rdata);
- rdata += elmt->size;
+ rdata += elt->size;
}
- elmt = elmt->next;
+ elt = elt->next;
}
}
rt.desc = 0;
{
size_t count = (Dynarr_length (pdump_root_objects) +
Dynarr_length (pdump_weak_object_chains));
- size_t i;
+ EMACS_INT i;
PDUMP_WRITE_ALIGNED (size_t, count);
PDUMP_ALIGN_OUTPUT (pdump_static_Lisp_Object);
pdump_static_Lisp_Object obj;
obj.address = Dynarr_at (pdump_root_objects, i);
obj.value = * obj.address;
-
+
if (POINTER_TYPE_P (XTYPE (obj.value)))
obj.value = wrap_object ((void *) pdump_get_entry (XRECORD_LHEADER (obj.value))->save_offset);
-
+
PDUMP_WRITE (pdump_static_Lisp_Object, obj);
}
for (i=0; i<Dynarr_length (pdump_weak_object_chains); i++)
{
- pdump_entry_list_elmt *elmt;
+ pdump_entry_list_elt *elt;
pdump_static_Lisp_Object obj;
obj.address = Dynarr_at (pdump_weak_object_chains, i);
obj.value = * obj.address;
-
+
for (;;)
{
const struct lrecord_description *desc;
int pos;
- elmt = pdump_get_entry (XRECORD_LHEADER (obj.value));
- if (elmt)
+ elt = pdump_get_entry (XRECORD_LHEADER (obj.value));
+ if (elt)
break;
desc = XRECORD_LHEADER_IMPLEMENTATION (obj.value)->description;
for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
obj.value = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj.value)));
}
- obj.value = wrap_object ((void *) elmt->save_offset);
+ obj.value = wrap_object ((void *) elt->save_offset);
PDUMP_WRITE (pdump_static_Lisp_Object, obj);
}
void
pdump (void)
{
- int i;
+ size_t i;
Lisp_Object t_console, t_device, t_frame;
int none;
pdump_header header;
+ pdump_object_table = xnew_array (pdump_entry_list, lrecord_type_count);
+ pdump_alert_undump_object = xnew_array (int, lrecord_type_count);
+
+ assert (ALIGNOF (max_align_t) <= pdump_align_table[0]);
+
+ for (i = 0; i < countof (pdump_align_table); i++)
+ if (pdump_align_table[i] > ALIGNOF (max_align_t))
+ pdump_align_table[i] = ALIGNOF (max_align_t);
+
flush_all_buffer_local_cache ();
/* These appear in a DEFVAR_LISP, which does a staticpro() */
t_frame = Vterminal_frame; Vterminal_frame = Qnil;
t_device = Vterminal_device; Vterminal_device = Qnil;
- dump_add_opaque (&lrecord_implementations_table,
+ dump_add_opaque ((void *) &lrecord_implementations_table,
lrecord_type_count * sizeof (lrecord_implementations_table[0]));
dump_add_opaque (&lrecord_markers,
lrecord_type_count * sizeof (lrecord_markers[0]));
- pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
+ pdump_hash = xnew_array_and_zero (pdump_entry_list_elt *, PDUMP_HASHSIZE);
for (i=0; i<lrecord_type_count; i++)
{
pdump_object_table[i].first = 0;
- pdump_object_table[i].align = 8;
+ pdump_object_table[i].align = ALIGNOF (max_align_t);
pdump_object_table[i].count = 0;
pdump_alert_undump_object[i] = 0;
}
pdump_struct_table.size = -1;
pdump_opaque_data_list.first = 0;
- pdump_opaque_data_list.align = 8;
+ pdump_opaque_data_list.align = ALIGNOF (max_align_t);
pdump_opaque_data_list.count = 0;
depth = 0;
if (!none)
return;
- for (i=0; i<Dynarr_length (pdump_root_struct_ptrs); i++)
+ for (i=0; i<(size_t)Dynarr_length (pdump_root_struct_ptrs); i++)
{
pdump_root_struct_ptr info = Dynarr_at (pdump_root_struct_ptrs, i);
pdump_register_struct (*(info.ptraddress), info.desc, 1);
pdump_dump_root_objects ();
fclose (pdump_out);
- close (pdump_fd);
+ /* pdump_fd is already closed by the preceding fclose call
+ close (pdump_fd); */
free (pdump_buf);
#else /* !WIN32_NATIVE */
-static void *pdump_mallocadr;
-
static void
pdump_file_free (void)
{
- xfree (pdump_mallocadr);
+ xfree (pdump_start);
}
#ifdef HAVE_MMAP
}
#endif /* HAVE_MMAP */
- pdump_mallocadr = xmalloc (pdump_length+255);
+ pdump_start = xnew_array (char, pdump_length);
pdump_free = pdump_file_free;
- pdump_start = (char *)((255 + (unsigned long)pdump_mallocadr) & ~255);
read (fd, pdump_start, pdump_length);
close (fd);
static int
pdump_file_try (char *exe_path)
{
- char *w;
+ char *w = exe_path + strlen (exe_path);
- w = exe_path + strlen (exe_path);
do
{
sprintf (w, "-%s-%08x.dmp", EMACS_VERSION, dump_id);
int
pdump_load (const char *argv0)
{
- char exe_path[PATH_MAX];
+ char exe_path[PATH_MAX], real_exe_path[PATH_MAX];
#ifdef WIN32_NATIVE
GetModuleFileName (NULL, exe_path, PATH_MAX);
+ /* #### urk, needed for xrealpath() below */
+ Vdirectory_sep_char = make_char ('\\');
#else /* !WIN32_NATIVE */
char *w;
const char *dir, *p;
}
strcpy (w, name);
- /* ### #$%$#^$^@%$^#%@$ ! */
-#ifdef access
-#undef access
-#endif
+ /* Check that exe_path is executable and not a directory */
+#undef access /* avoid !@#$%^& encapsulated access */
+#undef stat /* avoid !@#$%^& encapsulated stat */
+ {
+ struct stat statbuf;
+ if (access (exe_path, X_OK) == 0
+ && stat (exe_path, &statbuf) == 0
+ && ! S_ISDIR (statbuf.st_mode))
+ break;
+ }
- if (!access (exe_path, X_OK))
- break;
if (!*p)
{
/* Oh well, let's have some kind of default */
}
#endif /* WIN32_NATIVE */
- if (pdump_file_try (exe_path))
+ /* Save exe_path because pdump_file_try() modifies it */
+ strcpy(real_exe_path, exe_path);
+ if (pdump_file_try (exe_path)
+ || (xrealpath(real_exe_path, real_exe_path)
+ && pdump_file_try (real_exe_path)))
{
pdump_load_finish ();
return 1;