summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1995-10-15 00:59:48 +0000
committerRichard M. Stallman <rms@gnu.org>1995-10-15 00:59:48 +0000
commit806abf6f2a800f09c3833ad849baafabf73118a0 (patch)
treef2435562c72dcc97ddc25b5c3c231216d939304c
parent810ede4aeb40a6f4c2129c6249a3232a231270e1 (diff)
downloademacs-806abf6f2a800f09c3833ad849baafabf73118a0.tar.gz
(unexec): Find the old data section.
New variable new_offsets_shift used instead of new_data2_size since they are not always the same. Simplify logic for copying the headers and inserting new ones.
-rw-r--r--src/=unexsgi.c166
1 files changed, 100 insertions, 66 deletions
diff --git a/src/=unexsgi.c b/src/=unexsgi.c
index b375ee5a8a1..41df908d5a4 100644
--- a/src/=unexsgi.c
+++ b/src/=unexsgi.c
@@ -491,6 +491,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
Elf32_Word old_bss_size, new_data2_size;
Elf32_Off new_data2_offset;
Elf32_Addr new_data2_addr;
+ Elf32_Addr new_offsets_shift;
int n, nn, old_bss_index, old_data_index, new_data2_index;
int old_mdebug_index;
@@ -536,10 +537,9 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
break;
}
if (old_mdebug_index == old_file_h->e_shnum)
- old_mdebug_index = -1; /* just means no such section was present */
+ old_mdebug_index = -1; /* just means no such section was present */
- /* Find the old .bss section. Figure out parameters of the new
- data2 and bss sections. */
+ /* Find the old .bss section. */
for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
{
@@ -554,6 +554,24 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
if (old_bss_index == old_file_h->e_shnum)
fatal ("Can't find .bss in %s.\n", old_name, 0);
+ /* Find the old .data section. Figure out parameters of
+ the new data2 and bss sections. */
+
+ for (old_data_index = 1;
+ old_data_index < old_file_h->e_shnum;
+ old_data_index++)
+ {
+#ifdef DEBUG
+ fprintf (stderr, "Looking for .data - found %s\n",
+ old_section_names + OLD_SECTION_H(old_data_index).sh_name);
+#endif
+ if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
+ ".data"))
+ break;
+ }
+ if (old_data_index == old_file_h->e_shnum)
+ fatal ("Can't find .data in %s.\n", old_name, 0);
+
old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
#if defined(emacs) || !defined(DEBUG)
@@ -564,7 +582,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
#endif
new_data2_addr = old_bss_addr;
new_data2_size = new_bss_addr - old_bss_addr;
- new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
+ new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset +
+ (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
+ new_offsets_shift = new_bss_addr -
+ ((old_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0));
#ifdef DEBUG
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -574,6 +595,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
fprintf (stderr, "new_data2_size %x\n", new_data2_size);
fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
+ fprintf (stderr, "new_offsets_shift %x\n", new_offsets_shift);
#endif
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
@@ -587,7 +609,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
if (new_file < 0)
fatal ("Can't creat (%s): errno %d\n", new_name, errno);
- new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
+ new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_offsets_shift;
if (ftruncate (new_file, new_file_size))
fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
@@ -602,7 +624,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
new_section_h
= (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
- + new_data2_size);
+ + new_offsets_shift);
/* Make our new file, program and section headers as copies of the
originals. */
@@ -617,7 +639,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
/* Fix up file header. We'll add one section. Section header is
further away now. */
- new_file_h->e_shoff += new_data2_size;
+ new_file_h->e_shoff += new_offsets_shift;
new_file_h->e_shnum += 1;
#ifdef DEBUG
@@ -657,18 +679,18 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
if (n < 0)
fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
- NEW_PROGRAM_H (n).p_filesz += new_data2_size;
+ NEW_PROGRAM_H (n).p_filesz += new_offsets_shift;
NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
-#if 1 /* Maybe allow section after data2 - does this ever happen? */
+#if 1 /* Maybe allow section after data2 - does this ever happen? */
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
{
if (NEW_PROGRAM_H (n).p_vaddr
&& NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
- NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
+ NEW_PROGRAM_H (n).p_vaddr += new_offsets_shift - old_bss_size;
if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
- NEW_PROGRAM_H (n).p_offset += new_data2_size;
+ NEW_PROGRAM_H (n).p_offset += new_offsets_shift;
}
#endif
@@ -690,9 +712,17 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
{
caddr_t src;
- /* If it is bss section, insert the new data2 section before it. */
- if (n == old_bss_index)
+
+ if (n < old_bss_index)
+ {
+ memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
+ old_file_h->e_shentsize);
+
+ }
+ else if (n == old_bss_index)
{
+
+ /* If it is bss section, insert the new data2 section before it. */
/* Steal the data section header for this data2 section. */
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
new_file_h->e_shentsize);
@@ -710,28 +740,32 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
(caddr_t) OLD_SECTION_H (n).sh_addr,
new_data2_size);
nn++;
- }
+ memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
+ old_file_h->e_shentsize);
- memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
- old_file_h->e_shentsize);
-
- /* The new bss section's size is zero, and its file offset and virtual
- address should be off by NEW_DATA2_SIZE. */
- if (n == old_bss_index)
- {
- /* NN should be `old_bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
- NEW_SECTION_H (nn).sh_addr += new_data2_size;
+ /* The new bss section's size is zero, and its file offset and virtual
+ address should be off by NEW_OFFSETS_SHIFT. */
+ NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
+ NEW_SECTION_H (nn).sh_addr = new_bss_addr;
/* Let the new bss section address alignment be the same as the
section address alignment followed the old bss section, so
this section will be placed in exactly the same place. */
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
NEW_SECTION_H (nn).sh_size = 0;
}
- /* Any section that was original placed AFTER the bss section should now
- be off by NEW_DATA2_SIZE. */
- else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
+ else /* n > old_bss_index */
+ {
+
+ memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
+ old_file_h->e_shentsize);
+
+ }
+
+ /* Any section that was original placed AFTER the bss
+ section must now be adjusted by NEW_OFFSETS_SHIFT. */
+
+ if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
+ NEW_SECTION_H (nn).sh_offset += new_offsets_shift;
/* If any section hdr refers to the section after the new .data
section, make it refer to next one because we have inserted
@@ -753,8 +787,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
".data" in the strings table) get copied from the current process
instead of the old file. */
if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
- || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
- ".data1"))
+ || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1")
+ || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got"))
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
else
src = old_base + OLD_SECTION_H (n).sh_offset;
@@ -778,42 +812,42 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
n_phdrr->__fileaddr += movement; \
}
- HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
- HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
- unsigned movement = new_data2_size;
-
- MDEBUGADJUST (idnMax, cbDnOffset);
- MDEBUGADJUST (ipdMax, cbPdOffset);
- MDEBUGADJUST (isymMax, cbSymOffset);
- MDEBUGADJUST (ioptMax, cbOptOffset);
- MDEBUGADJUST (iauxMax, cbAuxOffset);
- MDEBUGADJUST (issMax, cbSsOffset);
- MDEBUGADJUST (issExtMax, cbSsExtOffset);
- MDEBUGADJUST (ifdMax, cbFdOffset);
- MDEBUGADJUST (crfd, cbRfdOffset);
- MDEBUGADJUST (iextMax, cbExtOffset);
- /* The Line Section, being possible off in a hole of the object,
- requires special handling. */
- if (n_phdrr->cbLine > 0)
- {
- if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
- + OLD_SECTION_H (n).sh_size))
- {
- /* line data is in a hole in elf. do special copy and adjust
- for this ld mistake.
- */
- n_phdrr->cbLineOffset += movement;
-
- memcpy (n_phdrr->cbLineOffset + new_base,
- o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
- }
- else
- {
- /* somehow line data is in .mdebug as it is supposed to be. */
- MDEBUGADJUST (cbLine, cbLineOffset);
- }
- }
- }
+ HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
+ HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
+ unsigned movement = new_offsets_shift;
+
+ MDEBUGADJUST (idnMax, cbDnOffset);
+ MDEBUGADJUST (ipdMax, cbPdOffset);
+ MDEBUGADJUST (isymMax, cbSymOffset);
+ MDEBUGADJUST (ioptMax, cbOptOffset);
+ MDEBUGADJUST (iauxMax, cbAuxOffset);
+ MDEBUGADJUST (issMax, cbSsOffset);
+ MDEBUGADJUST (issExtMax, cbSsExtOffset);
+ MDEBUGADJUST (ifdMax, cbFdOffset);
+ MDEBUGADJUST (crfd, cbRfdOffset);
+ MDEBUGADJUST (iextMax, cbExtOffset);
+ /* The Line Section, being possible off in a hole of the object,
+ requires special handling. */
+ if (n_phdrr->cbLine > 0)
+ {
+ if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
+ + OLD_SECTION_H (n).sh_size))
+ {
+ /* line data is in a hole in elf. do special copy and adjust
+ for this ld mistake.
+ */
+ n_phdrr->cbLineOffset += movement;
+
+ memcpy (n_phdrr->cbLineOffset + new_base,
+ o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
+ }
+ else
+ {
+ /* somehow line data is in .mdebug as it is supposed to be. */
+ MDEBUGADJUST (cbLine, cbLineOffset);
+ }
+ }
+ }
/* If it is the symbol table, its st_shndx field needs to be patched. */
if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB