Commit b6f8e806 authored by Gerd Moellmann's avatar Gerd Moellmann
Browse files

(unexec): Handle .rel.dyn section.

parent b5b41e02
......@@ -23,7 +23,6 @@ In other words, you are welcome to use, share and improve this program.
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 @@ what you give them. Help stamp out software-hoarding! */
/*
* 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 @@ what you give them. Help stamp out software-hoarding! */
#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 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
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 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
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 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
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 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
}
}
}
{
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 */
......
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