Mercurial > hg > xemacs-beta
diff src/unexelfsgi.c @ 50:ee648375d8d6 r19-16b91
Import from CVS: tag r19-16b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:56:41 +0200 |
parents | 376386a54a3c |
children | 8b0bdfdf0cf0 |
line wrap: on
line diff
--- a/src/unexelfsgi.c Mon Aug 13 08:56:06 2007 +0200 +++ b/src/unexelfsgi.c Mon Aug 13 08:56:41 2007 +0200 @@ -479,7 +479,12 @@ new_bss_addr - roundup(old_bss_addr,0x1000) */ - + /* Still more mods... Olivier Galibert 19971705 + - support for .sbss section (automagically changed to data without + name change) + - support for 64bits ABI (will need a bunch of fixes in the rest + of the code before it works + */ #include <sys/types.h> #include <stdio.h> @@ -492,6 +497,28 @@ #include <elf.h> #include <sym.h> /* for HDRR declaration */ #include <sys/mman.h> +#include <config.h> +#include "sysdep.h" + +/* in 64bits mode, use 64bits elf */ +#ifdef _ABI64 +typedef Elf64_Shdr l_Elf_Shdr; +typedef Elf64_Phdr l_Elf_Phdr; +typedef Elf64_Ehdr l_Elf_Ehdr; +typedef Elf64_Addr l_Elf_Addr; +typedef Elf64_Word l_Elf_Word; +typedef Elf64_Off l_Elf_Off; +typedef Elf64_Sym l_Elf_Sym; +#else +typedef Elf32_Shdr l_Elf_Shdr; +typedef Elf32_Phdr l_Elf_Phdr; +typedef Elf32_Ehdr l_Elf_Ehdr; +typedef Elf32_Addr l_Elf_Addr; +typedef Elf32_Word l_Elf_Word; +typedef Elf32_Off l_Elf_Off; +typedef Elf32_Sym l_Elf_Sym; +#endif + #ifndef emacs #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1) @@ -504,13 +531,13 @@ */ #define OLD_SECTION_H(n) \ - (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) + (*(l_Elf_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n))) #define NEW_SECTION_H(n) \ - (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) + (*(l_Elf_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n))) #define OLD_PROGRAM_H(n) \ - (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) + (*(l_Elf_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n))) #define NEW_PROGRAM_H(n) \ - (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) + (*(l_Elf_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n))) #define PATCH_INDEX(n) \ do { \ @@ -542,8 +569,8 @@ char *name; char *section_names; char *file_name; - Elf32_Ehdr *old_file_h; - Elf32_Shdr *old_section_h; + l_Elf_Ehdr *old_file_h; + l_Elf_Shdr *old_section_h; int noerror; { int idx; @@ -581,9 +608,9 @@ void unexec (new_name, old_name, data_start, bss_start, entry_address) char *new_name, *old_name; - unsigned data_start, bss_start, entry_address; + uintptr_t data_start, bss_start, entry_address; { - extern unsigned int bss_end; + extern uintptr_t bss_end; int new_file, old_file, new_file_size; /* Pointers to the base of the image of the two files. */ @@ -591,21 +618,22 @@ /* Pointers to the file, program and section headers for the old and new files. */ - Elf32_Ehdr *old_file_h, *new_file_h; - Elf32_Phdr *old_program_h, *new_program_h; - Elf32_Shdr *old_section_h, *new_section_h; + 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; /* Point to the section name table in the old file. */ char *old_section_names; - Elf32_Addr old_bss_addr, new_bss_addr; - Elf32_Word old_bss_size, new_data2_size; - Elf32_Off new_data2_offset; - Elf32_Addr new_data2_addr; - Elf32_Addr new_offsets_shift; + l_Elf_Addr old_bss_addr, new_bss_addr; + l_Elf_Addr old_base_addr; + l_Elf_Word old_bss_size, new_data2_size; + l_Elf_Off new_data2_offset, new_base_offset; + l_Elf_Addr new_data2_addr; + l_Elf_Addr new_offsets_shift; int n, nn, old_bss_index, old_data_index, new_data2_index; - int old_mdebug_index; + int old_mdebug_index, old_sbss_index; struct stat stat_buf; /* Open the old file & map it into the address space. */ @@ -630,9 +658,9 @@ /* Get pointers to headers & section names. */ - old_file_h = (Elf32_Ehdr *) old_base; - old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff); - old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff); + old_file_h = (l_Elf_Ehdr *) old_base; + old_program_h = (l_Elf_Phdr *) ((byte *) old_base + old_file_h->e_phoff); + old_section_h = (l_Elf_Shdr *) ((byte *) old_base + old_file_h->e_shoff); old_section_names = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset; @@ -641,6 +669,11 @@ old_mdebug_index = find_section (".mdebug", old_section_names, old_name, old_file_h, old_section_h, 1); + /* Find the .sbss section, if any. */ + + old_sbss_index = find_section (".sbss", old_section_names, + old_name, old_file_h, old_section_h, 1); + /* Find the old .bss section. */ old_bss_index = find_section (".bss", old_section_names, @@ -654,9 +687,10 @@ old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; + old_base_addr = old_sbss_index == -1 ? old_bss_addr : OLD_SECTION_H (old_sbss_index).sh_addr; #if defined(emacs) || !defined(DEBUG) - bss_end = (unsigned int) sbrk (0); - new_bss_addr = (Elf32_Addr) bss_end; + bss_end = (uintptr_t) sbrk (0); + new_bss_addr = (l_Elf_Addr) bss_end; #else new_bss_addr = old_bss_addr + old_bss_size + 0x1234; #endif @@ -664,13 +698,16 @@ 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_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_bss_addr & ~0xfff) + ((old_bss_addr & 0xfff) ? 0x1000 : 0)); + ((old_base_addr & ~0xfff) + ((old_base_addr & 0xfff) ? 0x1000 : 0)); #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_base_addr %x\n", old_base_addr); 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); @@ -702,10 +739,10 @@ if (new_base == (caddr_t) -1) fatal ("Can't mmap (%s): errno %d\n", new_name, errno); - new_file_h = (Elf32_Ehdr *) new_base; - new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff); + new_file_h = (l_Elf_Ehdr *) new_base; + new_program_h = (l_Elf_Phdr *) ((byte *) new_base + old_file_h->e_phoff); new_section_h - = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff + = (l_Elf_Shdr *) ((byte *) new_base + old_file_h->e_shoff + new_offsets_shift); /* Make our new file, program and section headers as copies of the @@ -747,7 +784,7 @@ /* Supposedly this condition is okay for the SGI. */ #if 0 - if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) + 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, 0); #endif @@ -755,11 +792,12 @@ && (round_up ((NEW_PROGRAM_H (n)).p_vaddr + (NEW_PROGRAM_H (n)).p_filesz, alignment) - == round_up (old_bss_addr, alignment))) + == round_up (old_base_addr, alignment))) break; } if (n < 0) - fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); + fatal ("Couldn't find segment next to %s in %s\n", + old_sbss_index == -1 ? ".sbss" : ".bss", old_name, 0); NEW_PROGRAM_H (n).p_filesz += new_offsets_shift; NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; @@ -843,7 +881,7 @@ /* 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) + if (NEW_SECTION_H (nn).sh_offset >= new_base_offset) NEW_SECTION_H (nn).sh_offset += new_offsets_shift; /* If any section hdr refers to the section after the new .data @@ -857,17 +895,26 @@ && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM) PATCH_INDEX (NEW_SECTION_H (nn).sh_info); + /* Fix the type and alignment for the .sbss section */ + if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sbss")) + { + NEW_SECTION_H (nn).sh_type = SHT_PROGBITS; + NEW_SECTION_H (nn).sh_offset = round_up (NEW_SECTION_H (nn).sh_offset, + NEW_SECTION_H (nn).sh_addralign); + } + /* Now, start to copy the content of sections. */ if (NEW_SECTION_H (nn).sh_type == SHT_NULL || NEW_SECTION_H (nn).sh_type == SHT_NOBITS) continue; - /* Write out the sections. .data and .data1 (and data2, called + /* Write out the sections. .data, .data1 and .sbss (and data2, called ".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, ".got")) + || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".got") + || !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sbss")) src = (caddr_t) OLD_SECTION_H (n).sh_addr; else src = old_base + OLD_SECTION_H (n).sh_offset; @@ -932,9 +979,9 @@ if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) { - Elf32_Shdr *spt = &NEW_SECTION_H (nn); + l_Elf_Shdr *spt = &NEW_SECTION_H (nn); unsigned int num = spt->sh_size / spt->sh_entsize; - Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset + l_Elf_Sym * sym = (l_Elf_Sym *) (NEW_SECTION_H (nn).sh_offset + new_base); for (; num--; sym++) {