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

(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.
parent 26fb39b5
......@@ -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
......
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