#ifdef emacs
#include <config.h>
#endif
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <a.out.h>
#ifdef HPUX_USE_SHLIBS
#include <dl.h>
#endif
static long brk_on_dump = 0;
int
run_time_remap (ignored)
char *ignored;
{
brk ((char *) brk_on_dump);
}
#undef roundup
#define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1))
#define min(x,y) (((x) < (y)) ? (x) : (y))
unexec (new_name, old_name, new_end_of_text, dummy1, dummy2)
char new_name[];
char old_name[];
char *new_end_of_text;
int dummy1, dummy2;
{
int old, new;
int old_size, new_size;
struct header hdr;
struct som_exec_auxhdr auxhdr;
long i;
old = open (old_name, O_RDONLY);
if (old < 0)
{ perror (old_name); exit (1); }
new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
if (new < 0)
{ perror (new_name); exit (1); }
read_header (old, &hdr, &auxhdr);
brk_on_dump = (long) sbrk (0);
old_size = auxhdr.exec_dsize;
i = (long) sbrk (0);
new_size = i - auxhdr.exec_dmem;
lseek (old, 0, 0);
copy_file (old, new, auxhdr.exec_dfile);
lseek (old, old_size, 1);
save_data_space (new, &hdr, &auxhdr, new_size);
copy_rest (old, new);
update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
write_header (new, &hdr, &auxhdr);
close (old);
close (new);
return 0;
}
save_data_space (file, hdr, auxhdr, size)
int file;
struct header *hdr;
struct som_exec_auxhdr *auxhdr;
int size;
{
if (write (file, auxhdr->exec_dmem, size) != size)
{ perror ("Can't save new data space"); exit (1); }
auxhdr->exec_dsize = size;
auxhdr->exec_bsize = 0;
}
update_file_ptrs (file, hdr, auxhdr, location, offset)
int file;
struct header *hdr;
struct som_exec_auxhdr *auxhdr;
unsigned int location;
int offset;
{
struct subspace_dictionary_record subspace;
int i;
hdr->som_length += offset;
#define update(ptr) if (ptr > location) ptr = ptr + offset
update (hdr->aux_header_location);
update (hdr->space_strings_location);
update (hdr->init_array_location);
update (hdr->compiler_location);
update (hdr->symbol_location);
update (hdr->fixup_request_location);
update (hdr->symbol_strings_location);
update (hdr->unloadable_sp_location);
update (auxhdr->exec_tfile);
update (auxhdr->exec_dfile);
lseek (file, hdr->subspace_location, 0);
for (i = 0; i < hdr->subspace_total; i++)
{
if (read (file, &subspace, sizeof (subspace)) != sizeof (subspace))
{ perror ("Can't read subspace record"); exit (1); }
if (subspace.initialization_length > 0
&& subspace.file_loc_init_value > location)
{
subspace.file_loc_init_value += offset;
lseek (file, -sizeof (subspace), 1);
if (write (file, &subspace, sizeof (subspace)) != sizeof (subspace))
{ perror ("Can't update subspace record"); exit (1); }
}
}
#undef update
}
read_header (file, hdr, auxhdr)
int file;
struct header *hdr;
struct som_exec_auxhdr *auxhdr;
{
lseek (file, 0, 0);
if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
{ perror ("Couldn't read header from a.out file"); exit (1); }
if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
&& hdr->a_magic != DEMAND_MAGIC)
{
fprintf (stderr, "a.out file doesn't have legal magic number\n");
exit (1);
}
lseek (file, hdr->aux_header_location, 0);
if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
{
perror ("Couldn't read auxiliary header from a.out file");
exit (1);
}
}
write_header (file, hdr, auxhdr)
int file;
struct header *hdr;
struct som_exec_auxhdr *auxhdr;
{
hdr->checksum = calculate_checksum (hdr);
lseek (file, 0, 0);
if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
{ perror ("Couldn't write header to a.out file"); exit (1); }
lseek (file, hdr->aux_header_location, 0);
if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
{ perror ("Couldn't write auxiliary header to a.out file"); exit (1); }
}
calculate_checksum (hdr)
struct header *hdr;
{
int checksum, i, *ptr;
checksum = 0; ptr = (int *) hdr;
for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
checksum ^= ptr[i];
return (checksum);
}
copy_file (old, new, size)
int new, old;
int size;
{
int len;
int buffer[8192];
for (; size > 0; size -= len)
{
len = min (size, sizeof (buffer));
if (read (old, buffer, len) != len)
{ perror ("Read failure on a.out file"); exit (1); }
if (write (new, buffer, len) != len)
{ perror ("Write failure in a.out file"); exit (1); }
}
}
copy_rest (old, new)
int new, old;
{
int buffer[4096];
int len;
while ((len = read (old, buffer, sizeof (buffer))) > 0)
if (write (new, buffer, len) != len) break;
if (len != 0)
{ perror ("Unable to copy the rest of the file"); exit (1); }
}
#ifdef DEBUG
display_header (hdr, auxhdr)
struct header *hdr;
struct som_exec_auxhdr *auxhdr;
{
printf ("\n\nFILE HEADER\n");
printf ("magic number %d \n", hdr->a_magic);
printf ("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
printf ("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
printf ("entry %x \n", auxhdr->exec_entry);
printf ("Bss segment size %u\n", auxhdr->exec_bsize);
printf ("\n");
printf ("data file loc %d size %d\n",
auxhdr->exec_dfile, auxhdr->exec_dsize);
printf ("som_length %d\n", hdr->som_length);
printf ("unloadable sploc %d size %d\n",
hdr->unloadable_sp_location, hdr->unloadable_sp_size);
}
#endif