/* Round X up to a multiple of Y. */
-int
-round_up (x, y)
- int x, y;
+static int
+round_up (int x, int y)
{
int rem = x % y;
if (rem == 0)
if NOERROR is 0; we return -1 if NOERROR is nonzero. */
static int
-find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
- char *name;
- char *section_names;
- char *file_name;
- l_Elf_Ehdr *old_file_h;
- l_Elf_Shdr *old_section_h;
- int noerror;
+find_section (char *name,
+ char *section_names,
+ char *file_name,
+ l_Elf_Ehdr *old_file_h,
+ l_Elf_Shdr *old_section_h,
+ int noerror)
{
int idx;
*
*/
int
-unexec (new_name, old_name, data_start, bss_start, entry_address)
- char *new_name, *old_name;
- uintptr_t data_start, bss_start, entry_address;
+unexec (char *new_name,
+ char *old_name,
+ uintptr_t data_start,
+ uintptr_t bss_start,
+ uintptr_t entry_address)
{
extern uintptr_t bss_end;
int new_file, old_file, new_file_size;
l_Elf_Ehdr *old_file_h, *new_file_h;
l_Elf_Phdr *old_program_h, *new_program_h;
l_Elf_Shdr *old_section_h, *new_section_h;
+ l_Elf_Shdr *oldbss;
/* Point to the section name table in the old file. */
char *old_section_names;
(new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
new_base_offset = OLD_SECTION_H (old_data_index).sh_offset +
(old_base_addr - OLD_SECTION_H (old_data_index).sh_addr);
- new_offsets_shift = new_bss_addr -
- ((old_base_addr & ~0xfff) + ((old_base_addr & 0xfff) ? 0x1000 : 0));
+ new_offsets_shift = new_bss_addr - (old_base_addr & ~0xfff) +
+ ((old_base_addr & 0xfff) ? 0x1000 : 0);
#ifdef DEBUG
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
/* Fix up a new program header. Extend the writable data segment so
that the bss area is covered too. Find that segment by looking
- for a segment that ends just before the .bss area. Make sure
- that no segments are above the new .data2. Put a loop at the end
- to adjust the offset and address of any segment that is above
- data2, just in case we decide to allow this later. */
+ for one that starts before and ends after the .bss and it PT_LOADable.
+ Put a loop at the end to adjust the offset and address of any segment
+ that is above data2, just in case we decide to allow this later. */
+ oldbss = &OLD_SECTION_H(old_bss_index);
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
{
/* Compute maximum of all requirements for alignment of section. */
- int alignment = (NEW_PROGRAM_H (n)).p_align;
- if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
- alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
-
- /* Supposedly this condition is okay for the SGI. */
-#if 0
- if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_base_addr)
- fatal ("Program segment above .bss in %s\n", old_name);
+ l_Elf_Phdr * ph = (l_Elf_Phdr *)((byte *) new_program_h +
+ new_file_h->e_phentsize*(n));
+#ifdef DEBUG
+ printf ("%d @ %0x + %0x against %0x + %0x",
+ n, ph->p_vaddr, ph->p_memsz,
+ oldbss->sh_addr, oldbss->sh_size);
+#endif
+ if ((ph->p_type == PT_LOAD) &&
+ (ph->p_vaddr <= oldbss->sh_addr) &&
+ ((ph->p_vaddr + ph->p_memsz)>=(oldbss->sh_addr + oldbss->sh_size))) {
+ ph->p_filesz += new_offsets_shift;
+ ph->p_memsz = ph->p_filesz;
+#ifdef DEBUG
+ puts (" That's the one!");
+ fflush (stdout);
+#endif
+ break;
+ }
+#ifdef DEBUG
+ putchar ('\n');
+ fflush (stdout);
#endif
-
- if (NEW_PROGRAM_H (n).p_type == PT_LOAD
- && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
- + (NEW_PROGRAM_H (n)).p_filesz,
- alignment)
- == round_up (old_base_addr, alignment)))
- break;
}
if (n < 0)
fatal ("Couldn't find segment next to %s in %s\n",
old_sbss_index == -1 ? ".sbss" : ".bss", old_name);
- 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? */
for (n = new_file_h->e_phnum - 1; n >= 0; n--)