(unexec): Handle unaligned bss offset.
This commit is contained in:
parent
1b7c198ad1
commit
826ba17e91
2 changed files with 30 additions and 17 deletions
|
@ -1,3 +1,7 @@
|
|||
2009-02-02 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* unexelf.c (unexec): Handle unaligned bss offset.
|
||||
|
||||
2009-02-01 Adrian Robert <Adrian.B.Robert@gmail.com>
|
||||
|
||||
* nsterm.m (ns_read_socket): Copy 2009-01-29 and 2009-01-30
|
||||
|
|
|
@ -27,8 +27,8 @@ what you give them. Help stamp out software-hoarding! */
|
|||
* unexec.c - Convert a running program into an a.out file.
|
||||
*
|
||||
* Author: Spencer W. Thomas
|
||||
* Computer Science Dept.
|
||||
* University of Utah
|
||||
* Computer Science Dept.
|
||||
* University of Utah
|
||||
* Date: Tue Mar 2 1982
|
||||
* Modified heavily since then.
|
||||
*
|
||||
|
@ -680,6 +680,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
ElfW(Word) old_bss_size, new_data2_size;
|
||||
ElfW(Off) new_data2_offset;
|
||||
ElfW(Addr) new_data2_addr;
|
||||
ElfW(Off) old_bss_offset;
|
||||
ElfW(Word) new_data2_incr;
|
||||
|
||||
int n, nn;
|
||||
int old_bss_index, old_sbss_index, old_plt_index;
|
||||
|
@ -754,6 +756,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
{
|
||||
old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
|
||||
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
|
||||
old_bss_offset = OLD_SECTION_H (old_bss_index).sh_offset;
|
||||
new_data2_index = old_bss_index;
|
||||
}
|
||||
else if (old_plt_index != -1
|
||||
|
@ -766,6 +769,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
+ OLD_SECTION_H (old_plt_index).sh_size;
|
||||
if (old_sbss_index != -1)
|
||||
old_bss_size += OLD_SECTION_H (old_sbss_index).sh_size;
|
||||
old_bss_offset = OLD_SECTION_H (old_plt_index).sh_offset;
|
||||
new_data2_index = old_plt_index;
|
||||
}
|
||||
else
|
||||
|
@ -773,6 +777,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
|
||||
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
|
||||
+ OLD_SECTION_H (old_sbss_index).sh_size;
|
||||
old_bss_offset = OLD_SECTION_H (old_sbss_index).sh_offset;
|
||||
new_data2_index = old_sbss_index;
|
||||
}
|
||||
|
||||
|
@ -789,17 +794,24 @@ 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_data_index).sh_offset +
|
||||
(new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
|
||||
new_data2_offset = OLD_SECTION_H (old_data_index).sh_offset
|
||||
+ (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
|
||||
/* This is the amount by which the sections following the bss sections
|
||||
must be shifted in the image. It can differ from new_data2_size if
|
||||
the end of the old .data section (and thus the offset of the .bss
|
||||
section) was unaligned. */
|
||||
new_data2_incr = new_data2_size + (new_data2_offset - old_bss_offset);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
|
||||
fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
|
||||
fprintf (stderr, "old_bss_size %x\n", old_bss_size);
|
||||
fprintf (stderr, "old_bss_offset %x\n", old_bss_offset);
|
||||
fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
|
||||
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_data2_incr %x\n", new_data2_incr);
|
||||
#endif
|
||||
|
||||
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
||||
|
@ -813,7 +825,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_data2_incr;
|
||||
|
||||
if (ftruncate (new_file, new_file_size))
|
||||
fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
|
||||
|
@ -826,7 +838,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
new_file_h = (ElfW(Ehdr) *) new_base;
|
||||
new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
|
||||
new_section_h = (ElfW(Shdr) *)
|
||||
((byte *) new_base + old_file_h->e_shoff + new_data2_size);
|
||||
((byte *) new_base + old_file_h->e_shoff + new_data2_incr);
|
||||
|
||||
/* Make our new file, program and section headers as copies of the
|
||||
originals. */
|
||||
|
@ -841,7 +853,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_data2_incr;
|
||||
new_file_h->e_shnum += 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -901,7 +913,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
NEW_PROGRAM_H (n).p_vaddr += new_data2_size - 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_data2_incr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -957,10 +969,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
)
|
||||
{
|
||||
/* NN should be `old_s?bss_index + 1' at this point. */
|
||||
NEW_SECTION_H (nn).sh_offset =
|
||||
NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
|
||||
NEW_SECTION_H (nn).sh_addr =
|
||||
NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
|
||||
NEW_SECTION_H (nn).sh_offset = new_data2_offset + new_data2_size;
|
||||
NEW_SECTION_H (nn).sh_addr = new_data2_addr + new_data2_size;
|
||||
/* 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. */
|
||||
|
@ -970,16 +980,15 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
else
|
||||
{
|
||||
/* Any section that was originally placed after the .bss
|
||||
section should now be off by NEW_DATA2_SIZE. If a
|
||||
section should now be off by NEW_DATA2_INCR. If a
|
||||
section overlaps the .bss section, consider it to be
|
||||
placed after the .bss section. Overlap can occur if the
|
||||
section just before .bss has less-strict alignment; this
|
||||
was observed between .symtab and .bss on Solaris 2.5.1
|
||||
(sparc) with GCC snapshot 960602. */
|
||||
|
||||
if (NEW_SECTION_H (nn).sh_offset + NEW_SECTION_H (nn).sh_size
|
||||
> new_data2_offset)
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||
if (NEW_SECTION_H (nn).sh_offset >= old_bss_offset)
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_incr;
|
||||
|
||||
/* Any section that was originally placed after the section
|
||||
header table should now be off by the size of one section
|
||||
|
@ -1084,7 +1093,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||
#if defined (_SYSTYPE_SYSV)
|
||||
if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
|
||||
&& old_mdebug_index != -1)
|
||||
{
|
||||
{
|
||||
int diff = NEW_SECTION_H(nn).sh_offset
|
||||
- OLD_SECTION_H(old_mdebug_index).sh_offset;
|
||||
HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
|
||||
|
|
Loading…
Add table
Reference in a new issue