mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-26 19:18:50 +00:00
(unexec): Handle debugging info properly.
This commit is contained in:
parent
c0096c73d7
commit
5416d1eee8
258
src/unexsgi.c
258
src/unexsgi.c
@ -418,6 +418,7 @@ Filesz Memsz Flags Align
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
#include <syms.h> /* for HDRR declaration */
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#ifndef emacs
|
#ifndef emacs
|
||||||
@ -474,17 +475,16 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
extern unsigned int bss_end;
|
extern unsigned int bss_end;
|
||||||
int new_file, old_file, new_file_size;
|
int new_file, old_file, new_file_size;
|
||||||
|
|
||||||
/* Pointers to the base of the image of the two files. */
|
/* Pointers to the base of the image of the two files. */
|
||||||
caddr_t old_base, new_base;
|
caddr_t old_base, new_base;
|
||||||
|
|
||||||
/* Pointers to the file, program and section headers for the old and new
|
/* Pointers to the file, program and section headers for the old and new
|
||||||
* files.
|
files. */
|
||||||
*/
|
|
||||||
Elf32_Ehdr *old_file_h, *new_file_h;
|
Elf32_Ehdr *old_file_h, *new_file_h;
|
||||||
Elf32_Phdr *old_program_h, *new_program_h;
|
Elf32_Phdr *old_program_h, *new_program_h;
|
||||||
Elf32_Shdr *old_section_h, *new_section_h;
|
Elf32_Shdr *old_section_h, *new_section_h;
|
||||||
|
|
||||||
/* Point to the section name table in the old file */
|
/* Point to the section name table in the old file. */
|
||||||
char *old_section_names;
|
char *old_section_names;
|
||||||
|
|
||||||
Elf32_Addr old_bss_addr, new_bss_addr;
|
Elf32_Addr old_bss_addr, new_bss_addr;
|
||||||
@ -493,9 +493,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
Elf32_Addr new_data2_addr;
|
Elf32_Addr new_data2_addr;
|
||||||
|
|
||||||
int n, nn, old_bss_index, old_data_index, new_data2_index;
|
int n, nn, old_bss_index, old_data_index, new_data2_index;
|
||||||
|
int old_mdebug_index;
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
|
|
||||||
/* Open the old file & map it into the address space. */
|
/* Open the old file & map it into the address space. */
|
||||||
|
|
||||||
old_file = open (old_name, O_RDONLY);
|
old_file = open (old_name, O_RDONLY);
|
||||||
|
|
||||||
@ -515,17 +516,30 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
old_base);
|
old_base);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get pointers to headers & section names */
|
/* Get pointers to headers & section names. */
|
||||||
|
|
||||||
old_file_h = (Elf32_Ehdr *) old_base;
|
old_file_h = (Elf32_Ehdr *) old_base;
|
||||||
old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
|
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_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
|
||||||
old_section_names = (char *) old_base
|
old_section_names
|
||||||
+ OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;
|
= (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
|
||||||
|
|
||||||
|
/* Find the mdebug section, if any. */
|
||||||
|
for (old_mdebug_index = 1; old_mdebug_index < old_file_h->e_shnum; old_mdebug_index++)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf (stderr, "Looking for .mdebug - found %s\n",
|
||||||
|
old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name);
|
||||||
|
#endif
|
||||||
|
if (!strcmp (old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name,
|
||||||
|
".mdebug"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (old_mdebug_index == old_file_h->e_shnum)
|
||||||
|
old_mdebug_index = -1; /* just means no such section was present */
|
||||||
|
|
||||||
/* Find the old .bss section. Figure out parameters of the new
|
/* Find the old .bss section. Figure out parameters of the new
|
||||||
* data2 and bss sections.
|
data2 and bss sections. */
|
||||||
*/
|
|
||||||
|
|
||||||
for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
|
for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
|
||||||
{
|
{
|
||||||
@ -540,8 +554,8 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
if (old_bss_index == old_file_h->e_shnum)
|
if (old_bss_index == old_file_h->e_shnum)
|
||||||
fatal ("Can't find .bss in %s.\n", old_name, 0);
|
fatal ("Can't find .bss in %s.\n", old_name, 0);
|
||||||
|
|
||||||
old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
|
old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
|
||||||
old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
|
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
|
||||||
#if defined(emacs) || !defined(DEBUG)
|
#if defined(emacs) || !defined(DEBUG)
|
||||||
bss_end = (unsigned int) sbrk (0);
|
bss_end = (unsigned int) sbrk (0);
|
||||||
new_bss_addr = (Elf32_Addr) bss_end;
|
new_bss_addr = (Elf32_Addr) bss_end;
|
||||||
@ -550,7 +564,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
#endif
|
#endif
|
||||||
new_data2_addr = old_bss_addr;
|
new_data2_addr = old_bss_addr;
|
||||||
new_data2_size = new_bss_addr - old_bss_addr;
|
new_data2_size = new_bss_addr - old_bss_addr;
|
||||||
new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
|
new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
|
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
|
||||||
@ -565,34 +579,33 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
||||||
fatal (".bss shrank when undumping???\n", 0, 0);
|
fatal (".bss shrank when undumping???\n", 0, 0);
|
||||||
|
|
||||||
/* Set the output file to the right size and mmap(2) it. Set
|
/* Set the output file to the right size and mmap it. Set
|
||||||
* pointers to various interesting objects. stat_buf still has
|
pointers to various interesting objects. stat_buf still has
|
||||||
* old_file data.
|
old_file data. */
|
||||||
*/
|
|
||||||
|
|
||||||
new_file = open (new_name, O_RDWR | O_CREAT, 0666);
|
new_file = open (new_name, O_RDWR | O_CREAT, 0666);
|
||||||
if (new_file < 0)
|
if (new_file < 0)
|
||||||
fatal ("Can't creat(%s): errno %d\n", new_name, errno);
|
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_size;
|
||||||
|
|
||||||
if (ftruncate (new_file, new_file_size))
|
if (ftruncate (new_file, new_file_size))
|
||||||
fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
|
fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
|
||||||
|
|
||||||
new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
new_file, 0);
|
new_file, 0);
|
||||||
|
|
||||||
if (new_base == (caddr_t) -1)
|
if (new_base == (caddr_t) -1)
|
||||||
fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
|
fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
|
||||||
|
|
||||||
new_file_h = (Elf32_Ehdr *) new_base;
|
new_file_h = (Elf32_Ehdr *) new_base;
|
||||||
new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
|
new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
|
||||||
new_section_h = (Elf32_Shdr *)
|
new_section_h
|
||||||
((byte *) new_base + old_file_h->e_shoff + new_data2_size);
|
= (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
|
||||||
|
+ new_data2_size);
|
||||||
|
|
||||||
/* Make our new file, program and section headers as copies of the
|
/* Make our new file, program and section headers as copies of the
|
||||||
* originals.
|
originals. */
|
||||||
*/
|
|
||||||
|
|
||||||
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
|
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
|
||||||
memcpy (new_program_h, old_program_h,
|
memcpy (new_program_h, old_program_h,
|
||||||
@ -602,8 +615,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
PATCH_INDEX (new_file_h->e_shstrndx);
|
PATCH_INDEX (new_file_h->e_shstrndx);
|
||||||
|
|
||||||
/* Fix up file header. We'll add one section. Section header is
|
/* Fix up file header. We'll add one section. Section header is
|
||||||
* further away now.
|
further away now. */
|
||||||
*/
|
|
||||||
|
|
||||||
new_file_h->e_shoff += new_data2_size;
|
new_file_h->e_shoff += new_data2_size;
|
||||||
new_file_h->e_shnum += 1;
|
new_file_h->e_shnum += 1;
|
||||||
@ -616,12 +628,11 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Fix up a new program header. Extend the writable data segment so
|
/* Fix up a new program header. Extend the writable data segment so
|
||||||
* that the bss area is covered too. Find that segment by looking
|
that the bss area is covered too. Find that segment by looking
|
||||||
* for a segment that ends just before the .bss area. Make sure
|
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
|
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
|
to adjust the offset and address of any segment that is above
|
||||||
* data2, just in case we decide to allow this later.
|
data2, just in case we decide to allow this later. */
|
||||||
*/
|
|
||||||
|
|
||||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||||
{
|
{
|
||||||
@ -632,11 +643,11 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
|
|
||||||
/* Supposedly this condition is okay for the SGI. */
|
/* Supposedly this condition is okay for the SGI. */
|
||||||
#if 0
|
#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_bss_addr)
|
||||||
fatal ("Program segment above .bss in %s\n", old_name, 0);
|
fatal ("Program segment above .bss in %s\n", old_name, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (NEW_PROGRAM_H(n).p_type == PT_LOAD
|
if (NEW_PROGRAM_H (n).p_type == PT_LOAD
|
||||||
&& (round_up ((NEW_PROGRAM_H (n)).p_vaddr
|
&& (round_up ((NEW_PROGRAM_H (n)).p_vaddr
|
||||||
+ (NEW_PROGRAM_H (n)).p_filesz,
|
+ (NEW_PROGRAM_H (n)).p_filesz,
|
||||||
alignment)
|
alignment)
|
||||||
@ -646,143 +657,194 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
|
|||||||
if (n < 0)
|
if (n < 0)
|
||||||
fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
|
fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
|
||||||
|
|
||||||
NEW_PROGRAM_H(n).p_filesz += new_data2_size;
|
NEW_PROGRAM_H (n).p_filesz += new_data2_size;
|
||||||
NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
|
NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
|
||||||
|
|
||||||
#if 1 /* Maybe allow section after data2 - does this ever happen? */
|
#if 1 /* Maybe allow section after data2 - does this ever happen? */
|
||||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||||
{
|
{
|
||||||
if (NEW_PROGRAM_H(n).p_vaddr
|
if (NEW_PROGRAM_H (n).p_vaddr
|
||||||
&& NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)
|
&& NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
|
||||||
NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;
|
NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
|
||||||
|
|
||||||
if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
|
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_size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Fix up section headers based on new .data2 section. Any section
|
/* Fix up section headers based on new .data2 section. Any section
|
||||||
* whose offset or virtual address is after the new .data2 section
|
whose offset or virtual address is after the new .data2 section
|
||||||
* gets its value adjusted. .bss size becomes zero and new address
|
gets its value adjusted. .bss size becomes zero and new address
|
||||||
* is set. data2 section header gets added by copying the existing
|
is set. data2 section header gets added by copying the existing
|
||||||
* .data header and modifying the offset, address and size.
|
.data header and modifying the offset, address and size. */
|
||||||
*/
|
|
||||||
for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
|
for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
|
||||||
old_data_index++)
|
old_data_index++)
|
||||||
if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
|
if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
|
||||||
".data"))
|
".data"))
|
||||||
break;
|
break;
|
||||||
if (old_data_index == old_file_h->e_shnum)
|
if (old_data_index == old_file_h->e_shnum)
|
||||||
fatal ("Can't find .data in %s.\n", old_name, 0);
|
fatal ("Can't find .data in %s.\n", old_name, 0);
|
||||||
|
|
||||||
/* Walk through all section headers, insert the new data2 section right
|
/* Walk through all section headers, insert the new data2 section right
|
||||||
before the new bss section. */
|
before the new bss section. */
|
||||||
for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
|
for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
|
||||||
{
|
{
|
||||||
caddr_t src;
|
caddr_t src;
|
||||||
/* If it is bss section, insert the new data2 section before it. */
|
/* If it is bss section, insert the new data2 section before it. */
|
||||||
if (n == old_bss_index)
|
if (n == old_bss_index)
|
||||||
{
|
{
|
||||||
/* Steal the data section header for this data2 section. */
|
/* Steal the data section header for this data2 section. */
|
||||||
memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(old_data_index),
|
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
|
||||||
new_file_h->e_shentsize);
|
new_file_h->e_shentsize);
|
||||||
|
|
||||||
NEW_SECTION_H(nn).sh_addr = new_data2_addr;
|
NEW_SECTION_H (nn).sh_addr = new_data2_addr;
|
||||||
NEW_SECTION_H(nn).sh_offset = new_data2_offset;
|
NEW_SECTION_H (nn).sh_offset = new_data2_offset;
|
||||||
NEW_SECTION_H(nn).sh_size = new_data2_size;
|
NEW_SECTION_H (nn).sh_size = new_data2_size;
|
||||||
/* Use the bss section's alignment. This will assure that the
|
/* Use the bss section's alignment. This will assure that the
|
||||||
new data2 section always be placed in the same spot as the old
|
new data2 section always be placed in the same spot as the old
|
||||||
bss section by any other application. */
|
bss section by any other application. */
|
||||||
NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(n).sh_addralign;
|
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
|
||||||
|
|
||||||
/* Now copy over what we have in the memory now. */
|
/* Now copy over what we have in the memory now. */
|
||||||
memcpy (NEW_SECTION_H(nn).sh_offset + new_base,
|
memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
|
||||||
(caddr_t) OLD_SECTION_H(n).sh_addr,
|
(caddr_t) OLD_SECTION_H (n).sh_addr,
|
||||||
new_data2_size);
|
new_data2_size);
|
||||||
nn++;
|
nn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (&NEW_SECTION_H(nn), &OLD_SECTION_H(n),
|
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
|
||||||
old_file_h->e_shentsize);
|
old_file_h->e_shentsize);
|
||||||
|
|
||||||
/* The new bss section's size is zero, and its file offset and virtual
|
/* The new bss section's size is zero, and its file offset and virtual
|
||||||
address should be off by NEW_DATA2_SIZE. */
|
address should be off by NEW_DATA2_SIZE. */
|
||||||
if (n == old_bss_index)
|
if (n == old_bss_index)
|
||||||
{
|
{
|
||||||
/* NN should be `old_bss_index + 1' at this point. */
|
/* NN should be `old_bss_index + 1' at this point. */
|
||||||
NEW_SECTION_H(nn).sh_offset += new_data2_size;
|
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||||
NEW_SECTION_H(nn).sh_addr += new_data2_size;
|
NEW_SECTION_H (nn).sh_addr += new_data2_size;
|
||||||
/* Let the new bss section address alignment be the same as the
|
/* Let the new bss section address alignment be the same as the
|
||||||
section address alignment followed the old bss section, so
|
section address alignment followed the old bss section, so
|
||||||
this section will be placed in exactly the same place. */
|
this section will be placed in exactly the same place. */
|
||||||
NEW_SECTION_H(nn).sh_addralign = OLD_SECTION_H(nn).sh_addralign;
|
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
|
||||||
NEW_SECTION_H(nn).sh_size = 0;
|
NEW_SECTION_H (nn).sh_size = 0;
|
||||||
}
|
}
|
||||||
/* Any section that was original placed AFTER the bss section should now
|
/* Any section that was original placed AFTER the bss section should now
|
||||||
be off by NEW_DATA2_SIZE. */
|
be off by NEW_DATA2_SIZE. */
|
||||||
else if (NEW_SECTION_H(nn).sh_offset >= new_data2_offset)
|
else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
|
||||||
NEW_SECTION_H(nn).sh_offset += new_data2_size;
|
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||||
|
|
||||||
/* If any section hdr refers to the section after the new .data
|
/* If any section hdr refers to the section after the new .data
|
||||||
section, make it refer to next one because we have inserted
|
section, make it refer to next one because we have inserted
|
||||||
a new section in between. */
|
a new section in between. */
|
||||||
|
|
||||||
PATCH_INDEX(NEW_SECTION_H(nn).sh_link);
|
PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
|
||||||
PATCH_INDEX(NEW_SECTION_H(nn).sh_info);
|
PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
|
||||||
|
|
||||||
/* Now, start to copy the content of sections. */
|
/* Now, start to copy the content of sections. */
|
||||||
if (NEW_SECTION_H(nn).sh_type == SHT_NULL
|
if (NEW_SECTION_H (nn).sh_type == SHT_NULL
|
||||||
|| NEW_SECTION_H(nn).sh_type == SHT_NOBITS)
|
|| NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Write out the sections. .data and .data1 (and data2, called
|
/* Write out the sections. .data and .data1 (and data2, called
|
||||||
* ".data" in the strings table) get copied from the current process
|
".data" in the strings table) get copied from the current process
|
||||||
* instead of the old file.
|
instead of the old file. */
|
||||||
*/
|
if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
|
||||||
if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
|
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
|
||||||
|| !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
|
|
||||||
".data1"))
|
".data1"))
|
||||||
src = (caddr_t) OLD_SECTION_H(n).sh_addr;
|
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
|
||||||
else
|
else
|
||||||
src = old_base + OLD_SECTION_H(n).sh_offset;
|
src = old_base + OLD_SECTION_H (n).sh_offset;
|
||||||
|
|
||||||
memcpy (NEW_SECTION_H(nn).sh_offset + new_base, src,
|
memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
|
||||||
NEW_SECTION_H(nn).sh_size);
|
NEW_SECTION_H (nn).sh_size);
|
||||||
|
|
||||||
|
/* Adjust the HDRR offsets in .mdebug and copy the
|
||||||
|
line data if it's in its usual 'hole' in the object.
|
||||||
|
Makes the new file debuggable with dbx.
|
||||||
|
patches up two problems: the absolute file offsets
|
||||||
|
in the HDRR record of .mdebug (see /usr/include/syms.h), and
|
||||||
|
the ld bug that gets the line table in a hole in the
|
||||||
|
elf file rather than in the .mdebug section proper.
|
||||||
|
David Anderson. davea@sgi.com Jan 16,1994. */
|
||||||
|
if (n == old_mdebug_index)
|
||||||
|
{
|
||||||
|
#define MDEBUGADJUST(__ct,__fileaddr) \
|
||||||
|
if (n_phdrr->__ct > 0) \
|
||||||
|
{ \
|
||||||
|
n_phdrr->__fileaddr += movement; \
|
||||||
|
}
|
||||||
|
|
||||||
|
HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
|
||||||
|
HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
|
||||||
|
unsigned movement = new_data2_size;
|
||||||
|
|
||||||
|
MDEBUGADJUST (idnMax, cbDnOffset);
|
||||||
|
MDEBUGADJUST (ipdMax, cbPdOffset);
|
||||||
|
MDEBUGADJUST (isymMax, cbSymOffset);
|
||||||
|
MDEBUGADJUST (ioptMax, cbOptOffset);
|
||||||
|
MDEBUGADJUST (iauxMax, cbAuxOffset);
|
||||||
|
MDEBUGADJUST (issMax, cbSsOffset);
|
||||||
|
MDEBUGADJUST (issExtMax, cbSsExtOffset);
|
||||||
|
MDEBUGADJUST (ifdMax, cbFdOffset);
|
||||||
|
MDEBUGADJUST (crfd, cbRfdOffset);
|
||||||
|
MDEBUGADJUST (iextMax, cbExtOffset);
|
||||||
|
/* The Line Section, being possible off in a hole of the object,
|
||||||
|
requires special handling. */
|
||||||
|
if (n_phdrr->cbLine > 0)
|
||||||
|
{
|
||||||
|
if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
|
||||||
|
+ OLD_SECTION_H (n).sh_size))
|
||||||
|
{
|
||||||
|
/* line data is in a hole in elf. do special copy and adjust
|
||||||
|
for this ld mistake.
|
||||||
|
*/
|
||||||
|
n_phdrr->cbLineOffset += movement;
|
||||||
|
|
||||||
|
memcpy (n_phdrr->cbLineOffset + new_base,
|
||||||
|
o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* somehow line data is in .mdebug as it is supposed to be. */
|
||||||
|
MDEBUGADJUST (cbLine, cbLineOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* If it is the symbol table, its st_shndx field needs to be patched. */
|
/* If it is the symbol table, its st_shndx field needs to be patched. */
|
||||||
if (NEW_SECTION_H(nn).sh_type == SHT_SYMTAB
|
if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
|
||||||
|| NEW_SECTION_H(nn).sh_type == SHT_DYNSYM)
|
|| NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
|
||||||
{
|
{
|
||||||
Elf32_Shdr *spt = &NEW_SECTION_H(nn);
|
Elf32_Shdr *spt = &NEW_SECTION_H (nn);
|
||||||
unsigned int num = spt->sh_size / spt->sh_entsize;
|
unsigned int num = spt->sh_size / spt->sh_entsize;
|
||||||
Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H(nn).sh_offset +
|
Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset
|
||||||
new_base);
|
+ new_base);
|
||||||
for (; num--; sym++)
|
for (; num--; sym++)
|
||||||
{
|
{
|
||||||
if ((sym->st_shndx == SHN_UNDEF)
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|| (sym->st_shndx == SHN_ABS)
|
|| sym->st_shndx == SHN_ABS
|
||||||
|| (sym->st_shndx == SHN_COMMON))
|
|| sym->st_shndx == SHN_COMMON)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PATCH_INDEX(sym->st_shndx);
|
PATCH_INDEX (sym->st_shndx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close the files and make the new file executable */
|
/* Close the files and make the new file executable. */
|
||||||
|
|
||||||
if (close (old_file))
|
if (close (old_file))
|
||||||
fatal ("Can't close(%s): errno %d\n", old_name, errno);
|
fatal ("Can't close (%s): errno %d\n", old_name, errno);
|
||||||
|
|
||||||
if (close (new_file))
|
if (close (new_file))
|
||||||
fatal ("Can't close(%s): errno %d\n", new_name, errno);
|
fatal ("Can't close (%s): errno %d\n", new_name, errno);
|
||||||
|
|
||||||
if (stat (new_name, &stat_buf) == -1)
|
if (stat (new_name, &stat_buf) == -1)
|
||||||
fatal ("Can't stat(%s): errno %d\n", new_name, errno);
|
fatal ("Can't stat (%s): errno %d\n", new_name, errno);
|
||||||
|
|
||||||
n = umask (777);
|
n = umask (777);
|
||||||
umask (n);
|
umask (n);
|
||||||
stat_buf.st_mode |= 0111 & ~n;
|
stat_buf.st_mode |= 0111 & ~n;
|
||||||
if (chmod (new_name, stat_buf.st_mode) == -1)
|
if (chmod (new_name, stat_buf.st_mode) == -1)
|
||||||
fatal ("Can't chmod(%s): errno %d\n", new_name, errno);
|
fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user