Mercurial > emacs
changeset 26473:762c51f4a100
(unexec): Handle .rel.dyn section.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Wed, 17 Nov 1999 20:58:06 +0000 |
parents | 596447fe8f0d |
children | 027b7c42a65b |
files | src/unexsni.c |
diffstat | 1 files changed, 86 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/unexsni.c Tue Nov 16 19:51:07 1999 +0000 +++ b/src/unexsni.c Wed Nov 17 20:58:06 1999 +0000 @@ -23,7 +23,6 @@ You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! */ - /* * unexec.c - Convert a running program into an a.out file. * @@ -117,6 +116,7 @@ /* * New modifications for Siemens Nixdorf's MIPS-based machines. * Marco.Walther@mch.sni.de + * marco@inreach.com * * The problem: Before the bss segment we have a so called sbss segment * (small bss) and maybe an sdata segment. These segments @@ -305,6 +305,9 @@ #include <fcntl.h> #include <elf.h> #include <sys/mman.h> +#include <assert.h> + +/* #define DEBUG */ #ifndef emacs #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1) @@ -383,6 +386,11 @@ Elf32_Addr new_data2_addr; Elf32_Addr new_data3_addr; + + Elf32_Addr old_rel_dyn_addr; + Elf32_Word old_rel_dyn_size; + int old_rel_dyn_index; + Elf32_Word old_sdata_size, new_sdata_size; int old_sdata_index = 0; @@ -463,6 +471,26 @@ if (old_sbss_index != (old_bss_index - 1)) fatal (".sbss should come immediately before .bss in %s.\n", old_name, 0); + /* Find the old .rel.dyn section. + */ + + for (old_rel_dyn_index = 1; old_rel_dyn_index < old_file_h->e_shnum; + old_rel_dyn_index++) + { +#ifdef DEBUG + fprintf (stderr, "Looking for .rel.dyn - found %s\n", + old_section_names + OLD_SECTION_H(old_rel_dyn_index).sh_name); +#endif + if (!strcmp (old_section_names + OLD_SECTION_H(old_rel_dyn_index).sh_name, + ".rel.dyn")) + break; + } + if (old_rel_dyn_index == old_file_h->e_shnum) + fatal ("Can't find .rel_dyn in %s.\n", old_name, 0); + + old_rel_dyn_addr = OLD_SECTION_H(old_rel_dyn_index).sh_addr; + old_rel_dyn_size = OLD_SECTION_H(old_rel_dyn_index).sh_size; + /* Figure out parameters of the new data3 and data2 sections. * Change the sbss and bss sections. */ @@ -516,6 +544,8 @@ fprintf (stderr, "old_sbss_index %d\n", old_sbss_index); fprintf (stderr, "old_sbss_addr %x\n", old_sbss_addr); fprintf (stderr, "old_sbss_size %x\n", old_sbss_size); + fprintf (stderr, "old_rel_dyn_addr %x\n", old_rel_dyn_addr); + fprintf (stderr, "old_rel_dyn_size %x\n", old_rel_dyn_size); if (old_sdata_index) { fprintf (stderr, "old_sdata_size %x\n", old_sdata_size); @@ -816,6 +846,61 @@ } } } + { + Elf32_Rel *rel_p; + unsigned int old_data_addr_start; + unsigned int old_data_addr_end; + unsigned int old_data_offset; + unsigned int new_data_offset; + int i; + + rel_p = (Elf32_Rel *)OLD_SECTION_H(old_rel_dyn_index).sh_addr; + old_data_addr_start = OLD_SECTION_H(old_data_index).sh_addr; + old_data_addr_end = old_data_addr_start + + OLD_SECTION_H(old_data_index).sh_size; + old_data_offset = (int)OLD_SECTION_H(old_data_index).sh_offset + + (unsigned int)old_base; + new_data_offset = (int)NEW_SECTION_H(old_data_index).sh_offset + + (unsigned int)new_base; + +#ifdef DEBUG + fprintf(stderr, "old_data.sh_addr= 0x%08x ... 0x%08x\n", old_data_addr_start, + old_data_addr_end); +#endif /* DEBUG */ + + for (i = 0; i < old_rel_dyn_size/sizeof(Elf32_Rel); i++) + { +#ifdef DEBUG + fprintf(stderr, ".rel.dyn offset= 0x%08x type= %d sym= %d\n", + rel_p->r_offset, ELF32_R_TYPE(rel_p->r_info), ELF32_R_SYM(rel_p->r_info)); +#endif /* DEBUG */ + + if (rel_p->r_offset) + { + unsigned int offset; + + assert(old_data_addr_start <= rel_p->r_offset && + rel_p->r_offset <= old_data_addr_end); + + offset = rel_p->r_offset - old_data_addr_start; + +#ifdef DEBUG + fprintf(stderr, "r_offset= 0x%08x *r_offset= 0x%08x\n", + rel_p->r_offset, *((int *)(rel_p->r_offset))); + fprintf(stderr, "old = 0x%08x *old =0x%08x\n", + (old_data_offset + offset - (unsigned int)old_base), + *((int *)(old_data_offset + offset))); + fprintf(stderr, "new = 0x%08x *new =0x%08x\n", + (new_data_offset + offset - (unsigned int)new_base), + *((int *)(new_data_offset + offset))); +#endif /* DEBUG */ + + *((int *)(new_data_offset + offset)) = *((int *)(old_data_offset + offset)); + } + + rel_p++; + } + } /* Close the files and make the new file executable */