Commit 4a438fc5 authored by Richard M. Stallman's avatar Richard M. Stallman
Browse files

Handle both AIX 3.2 and 4.1 bind output.

(make_hdr): Handle data_start being non-zero for 4.1.  Padding
sections are omitted in 4.1, but padding bytes can still be
present.  Calculate bias directly from first real section following bss.

(copy_text_and_data): Correct data section starting point for 4.1.

(adjust_lnnoptrs): Adjust line number pointers correctly for both
3.2 and 4.1, based on published IBM documentation.

(unrelocate_symbols): Compute and subtract relocation offsets for
text and data sections.  Handle data_start being non-zero for 4.1.
Skip unnecessary writes.
parent e024a2f4
......@@ -33,6 +33,14 @@ what you give them. Help stamp out software-hoarding! */
* Date: Tue Mar 2 1982
* Modified heavily since then.
*
* Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996
* As of AIX 4.1, text, data, and bss are pre-relocated by the binder in
* such a way that the file can be mapped with code in one segment and
* data/bss in another segment, without reading or copying the file, by
* the AIX exec loader. Padding sections are omitted, nevertheless
* small amounts of 'padding' still occurs between sections in the file.
* As modified, this code handles both 3.2 and 4.1 conventions.
*
* Synopsis:
* unexec (new_name, a_name, data_start, bss_start, entry_address)
* char *new_name, *a_name;
......@@ -203,21 +211,20 @@ extern int _end;
#endif /* not UMAX */
#endif /* Not STRIDE */
#endif /* not USG */
static long block_copy_start; /* Old executable start point */
static struct filehdr f_hdr; /* File header */
static struct aouthdr f_ohdr; /* Optional file header (a.out) */
long bias; /* Bias to add for growth */
long lnnoptr; /* Pointer to line-number info within file */
#define SYMS_START block_copy_start
static long text_scnptr;
static long data_scnptr;
#ifdef XCOFF
#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
static long load_scnptr;
static long orig_load_scnptr;
static long orig_data_scnptr;
#endif
static long data_st;
static ulong data_st; /* start of data area written out */
#ifndef MAX_SECTIONS
#define MAX_SECTIONS 10
......@@ -381,7 +388,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
#ifdef COFF
/* Salvage as much info from the existing file as possible */
block_copy_start = 0;
f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
if (a_out >= 0)
......@@ -390,14 +396,12 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
{
PERROR (a_name);
}
block_copy_start += sizeof (f_hdr);
if (f_hdr.f_opthdr > 0)
{
if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
{
PERROR (a_name);
}
block_copy_start += sizeof (f_ohdr);
}
if (f_hdr.f_nscns > MAX_SECTIONS)
{
......@@ -410,11 +414,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
{
PERROR (a_name);
}
if (s->s_scnptr > 0L)
{
if (block_copy_start < s->s_scnptr + s->s_size)
block_copy_start = s->s_scnptr + s->s_size;
}
#define CHECK_SCNHDR(ptr, name, flags) \
if (strcmp(s->s_name, name) == 0) { \
......@@ -459,7 +458,11 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
/* Now we alter the contents of all the f_*hdr variables
to correspond to what we want to dump. */
f_hdr.f_flags |= (F_RELFLG | F_EXEC); /* Why? */
/* Indicate that the reloc information is no longer valid for ld (bind);
we only update it enough to fake out the exec-time loader. */
f_hdr.f_flags |= (F_RELFLG | F_EXEC);
#ifdef EXEC_MAGIC
f_ohdr.magic = EXEC_MAGIC;
#endif
......@@ -467,73 +470,77 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
f_ohdr.tsize = data_start - f_ohdr.text_start;
f_ohdr.text_start = (long) start_of_text ();
#endif
f_ohdr.dsize = bss_start - ((unsigned) &_data);
data_st = f_ohdr.data_start ? f_ohdr.data_start : (ulong) &_data;
f_ohdr.dsize = bss_start - data_st;
f_ohdr.bsize = bss_end - bss_start;
f_dhdr->s_size = f_ohdr.dsize;
f_bhdr->s_size = f_ohdr.bsize;
f_bhdr->s_paddr = f_ohdr.dsize;
f_bhdr->s_vaddr = f_ohdr.dsize;
f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
/* fix scnptr's */
{
long ptr;
ulong ptr = section[0].s_scnptr;
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
struct scnhdr *s = &section[scns];
if (scns == 0)
ptr = s->s_scnptr;
bias = -1;
for (scns = 0; scns < f_hdr.f_nscns; scns++)
{
struct scnhdr *s = &section[scns];
if (s->s_scnptr != 0)
{
if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */
{
/*
* the text_start should probably be o_algntext but that doesn't
* seem to change
*/
if (f_ohdr.text_start != 0) /* && scns != 0 */
{
s->s_size = 512 - (ptr % 512);
if (s->s_size == 512)
s->s_size = 0;
}
s->s_scnptr = ptr;
}
else if (s->s_flags & STYP_DATA)
s->s_scnptr = ptr;
}
if ((s->s_flags & 0xffff) == STYP_PAD)
{
/*
* the text_start should probably be o_algntext but that doesn't
* seem to change
*/
if (f_ohdr.text_start != 0) /* && scns != 0 */
{
s->s_size = 512 - (s->s_scnptr % 512);
if (s->s_size == 512)
s->s_size = 0;
}
}
ptr = ptr + s->s_size;
}
else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
{
if (bias == -1) /* if first section after bss */
bias = ptr - s->s_scnptr;
bias = ptr - block_copy_start;
s->s_scnptr += bias;
ptr = s->s_scnptr;
}
ptr = ptr + s->s_size;
}
}
/* fix other pointers */
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
struct scnhdr *s = &section[scns];
for (scns = 0; scns < f_hdr.f_nscns; scns++)
{
struct scnhdr *s = &section[scns];
if (s->s_relptr != 0)
{
s->s_relptr += bias;
}
if (s->s_lnnoptr != 0)
{
if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
s->s_lnnoptr += bias;
}
}
if (s->s_relptr != 0)
{
s->s_relptr += bias;
}
if (s->s_lnnoptr != 0)
{
if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
s->s_lnnoptr += bias;
}
}
if (f_hdr.f_symptr > 0L)
{
f_hdr.f_symptr += bias;
}
data_st = data_start;
text_scnptr = f_thdr->s_scnptr;
data_scnptr = f_dhdr->s_scnptr;
load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
block_copy_start = orig_load_scnptr;
#ifdef ADJUST_EXEC_HEADER
ADJUST_EXEC_HEADER
......@@ -583,7 +590,7 @@ copy_text_and_data (new)
write_segment (new, ptr, end);
lseek (new, (long) data_scnptr, 0);
ptr = (char *) &_data;
ptr = (char *) data_st;
end = ptr + f_ohdr.dsize;
write_segment (new, ptr, end);
......@@ -644,13 +651,13 @@ copy_sym (new, a_out, a_name, new_name)
if (a_out < 0)
return 0;
if (SYMS_START == 0L)
if (orig_load_scnptr == 0L)
return 0;
if (lnnoptr && lnnoptr < SYMS_START) /* if there is line number info */
lseek (a_out, lnnoptr, 0); /* start copying from there */
if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */
lseek (a_out, lnnoptr, 0); /* start copying from there */
else
lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
lseek (a_out, orig_load_scnptr, 0); /* Position a.out to symtab. */
while ((n = read (a_out, page, sizeof page)) > 0)
{
......@@ -703,6 +710,8 @@ mark_x (name)
* the auxiliary entries that need adjustment, this routine will
* be fixed. As it is now, all such entries are wrong and sdb
* will complain. Fred Fish, UniSoft Systems Inc.
*
* I believe this is now fixed correctly. Bill Mann
*/
#ifdef COFF
......@@ -743,15 +752,17 @@ adjust_lnnoptrs (writedesc, readdesc, new_name)
for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
{
read (new, &symentry, SYMESZ);
for (naux = 0; naux < symentry.n_numaux; naux++)
for (naux = symentry.n_numaux; naux-- != 0; )
{
read (new, &auxentry, AUXESZ);
nsyms++;
if (ISFCN (symentry.n_type)) {
auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
lseek (new, -AUXESZ, 1);
write (new, &auxentry, AUXESZ);
}
if (naux != 0 /* skip csect auxentry (last entry) */
&& (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
{
auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
lseek (new, -AUXESZ, 1);
write (new, &auxentry, AUXESZ);
}
}
}
close (new);
......@@ -774,8 +785,8 @@ unrelocate_symbols (new, a_out, a_name, new_name)
register LDREL *ldrel;
LDHDR ldhdr;
LDREL ldrel_buf [20];
ulong t_start = (ulong) &_text;
ulong d_start = (ulong) &_data;
ulong t_reloc = (ulong) &_text - f_ohdr.text_start;
ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2);
int * p;
int dirty;
......@@ -837,49 +848,37 @@ unrelocate_symbols (new, a_out, a_name, new_name)
{
int orig_int;
#ifdef AIX4_1
lseek (a_out, orig_data_scnptr + (ldrel->l_vaddr - d_start), 0);
#else
lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);
#endif
lseek (a_out,
orig_data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0);
if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
{
PERROR (a_name);
}
p = (int *) (ldrel->l_vaddr + d_reloc);
switch (ldrel->l_symndx) {
case SYMNDX_TEXT:
#ifdef AIX4_1
p = (int *) (ldrel->l_vaddr);
orig_int = * p;
#else
p = (int *) (d_start + ldrel->l_vaddr);
orig_int = * p - (t_start - f_ohdr.text_start);
#endif
orig_int = * p - t_reloc;
break;
case SYMNDX_DATA:
case SYMNDX_BSS:
#ifdef AIX4_1
p = (int *) (ldrel->l_vaddr);
orig_int = * p;
#else
p = (int *) (d_start + ldrel->l_vaddr);
orig_int = * p - (d_start - f_ohdr.data_start);
#endif
orig_int = * p - d_reloc;
break;
}
#ifdef AIX4_1
lseek (new, data_scnptr + (ldrel->l_vaddr - d_start), 0);
#else
lseek (new, data_scnptr + ldrel->l_vaddr, 0);
#endif
if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
{
PERROR (new_name);
}
if (orig_int != * p)
{
lseek (new,
data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0);
if (write (new, (void *) &orig_int, sizeof (orig_int))
!= sizeof (orig_int))
{
PERROR (new_name);
}
}
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment