summaryrefslogtreecommitdiff
path: root/src/unexelf.c
diff options
context:
space:
mode:
authorKarl Heuer <kwzh@gnu.org>1999-08-25 16:15:29 +0000
committerKarl Heuer <kwzh@gnu.org>1999-08-25 16:15:29 +0000
commit48b562e858217c96552d345f798656f639ebe070 (patch)
treea6259ac8a890408632ccdc0ced59393808752bba /src/unexelf.c
parent58ddb8d71efceb22098d9b13b32c7f21acc38356 (diff)
downloademacs-48b562e858217c96552d345f798656f639ebe070.tar.gz
Merge IRIX debugging info patch from unexsgi.c
Auto-detect .sbss section. (round_up): Make it static. (unexec): Declare alignment as Elf Word. Skip ``Program segment above .bss'' test on MIPS without .sbss. Copy sections .got and .sdata1 sections. Adjust offsets in sections .sdata, .lit4, .lit8, .got and .sdata1.
Diffstat (limited to 'src/unexelf.c')
-rw-r--r--src/unexelf.c145
1 files changed, 96 insertions, 49 deletions
diff --git a/src/unexelf.c b/src/unexelf.c
index bf4f40cca0c..7fa8eb00ce0 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -427,16 +427,10 @@ Filesz Memsz Flags Align
#if defined (__sony_news) && defined (_SYSTYPE_SYSV)
#include <sys/elf_mips.h>
#include <sym.h>
-#define HAS_SBSS_SECTION
#endif /* __sony_news && _SYSTYPE_SYSV */
-
-#if defined (__NetBSD__) && defined (__powerpc__)
-#define HAS_SBSS_SECTION
-#endif
-
-#if defined (__linux__) && defined (__alpha__)
-#define HAS_SBSS_SECTION
-#endif
+#if __sgi
+#include <sym.h> /* for HDRR declaration */
+#endif /* __sgi */
#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
/* Declare COFF debugging symbol table. This used to be in
@@ -543,7 +537,7 @@ extern void fatal (char *, ...);
/* Get the address of a particular section or program header entry,
* accounting for the size of the entries.
*/
-/*
+/*
On PPC Reference Platform running Solaris 2.5.1
the plt section is also of type NOBI like the bss section.
(not really stored) and therefore sections after the bss
@@ -552,7 +546,7 @@ extern void fatal (char *, ...);
Thus, we modify the test from
if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
to
- if (NEW_SECTION_H (nn).sh_offset >=
+ if (NEW_SECTION_H (nn).sh_offset >=
OLD_SECTION_H (old_bss_index-1).sh_offset)
This is just a hack. We should put the new data section
before the .plt section.
@@ -584,7 +578,7 @@ typedef unsigned char byte;
/* Round X up to a multiple of Y. */
-ElfW(Addr)
+static ElfW(Addr)
round_up (x, y)
ElfW(Addr) x, y;
{
@@ -629,9 +623,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
ElfW(Addr) new_data2_addr;
int n, nn, old_bss_index, old_data_index, new_data2_index;
-#if defined (HAS_SBSS_SECTION)
int old_sbss_index, old_mdebug_index;
-#endif /* HAS_SBSS_SECTION */
struct stat stat_buf;
/* Open the old file & map it into the address space. */
@@ -681,7 +673,6 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
if (old_bss_index == old_file_h->e_shnum)
fatal ("Can't find .bss in %s.\n", old_name, 0);
-#if defined (HAS_SBSS_SECTION)
for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum;
old_sbss_index++)
{
@@ -695,6 +686,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
}
if (old_sbss_index == old_file_h->e_shnum)
{
+ old_sbss_index = -1;
old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
@@ -722,10 +714,7 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
}
if (old_mdebug_index == old_file_h->e_shnum)
old_mdebug_index = 0;
-#else /* not HAS_SBSS_SECTION */
- old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
- old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
-#endif /* not HAS_SBSS_SECTION */
+
#if defined (emacs) || !defined (DEBUG)
new_bss_addr = (ElfW(Addr)) sbrk (0);
#else
@@ -733,9 +722,6 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
#endif
new_data2_addr = old_bss_addr;
new_data2_size = new_bss_addr - old_bss_addr;
-#if !defined (HAS_SBSS_SECTION)
- new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
-#endif /* not HAS_SBSS_SECTION */
#ifdef DEBUG
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
@@ -816,18 +802,22 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
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;
+ ElfW(Word) 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;
-#if defined (HAS_SBSS_SECTION)
+#ifdef __mips
+ /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
+ and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
+ always get "Program segment above .bss" when dumping
+ when the executable doesn't have an sbss section. */
+ if (old_sbss_index != -1)
+#endif /* __mips */
if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
- > round_up (old_bss_addr, alignment))
- fatal ("Program segment above .bss in %s\n", old_name, 0);
-#else /* not HAS_SBSS_SECTION */
- 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);
-#endif /* not HAS_SBSS_SECTION */
+ > (old_sbss_index == -1
+ ? old_bss_addr
+ : round_up (old_bss_addr, alignment)))
+ fatal ("Program segment above .bss in %s\n", old_name, 0);
if (NEW_PROGRAM_H (n).p_type == PT_LOAD
&& (round_up ((NEW_PROGRAM_H (n)).p_vaddr
@@ -875,17 +865,10 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
{
caddr_t src;
- int temp_index;
-#if defined (HAS_SBSS_SECTION)
/* If it is (s)bss section, insert the new data2 section before it. */
/* new_data2_index is the index of either old_sbss or old_bss, that was
chosen as a section for new_data2. */
- temp_index = new_data2_index;
-#else /* not HAS_SBSS_SECTION */
- /* If it is bss section, insert the new data2 section before it. */
- temp_index = old_bss_index;
-#endif /* not HAS_SBSS_SECTION */
- if (n == temp_index)
+ if (n == new_data2_index)
{
/* Steal the data section header for this data2 section. */
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
@@ -910,16 +893,16 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
old_file_h->e_shentsize);
if (n == old_bss_index
-#if defined (HAS_SBSS_SECTION)
/* The new bss and sbss section's size is zero, and its file offset
and virtual address should be off by NEW_DATA2_SIZE. */
|| n == old_sbss_index
-#endif /* HAS_SBSS_SECTION */
)
{
- /* NN should be `old_bss_index + 1' at this point. */
- NEW_SECTION_H (nn).sh_offset += new_data2_size;
- NEW_SECTION_H (nn).sh_addr += new_data2_size;
+ /* NN should be `old_s?bss_index + 1' at this point. */
+ NEW_SECTION_H (nn).sh_offset =
+ NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
+ NEW_SECTION_H (nn).sh_addr =
+ NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
/* Let the new bss section address alignment be the same as the
section address alignment followed the old bss section, so
this section will be placed in exactly the same place. */
@@ -975,18 +958,16 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
".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")
-#ifdef _nec_ews_svr4 /* hir, 1994.6.13 */
- || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
- ".sdata")
-#endif
-#if defined (HAS_SBSS_SECTION)
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".sdata")
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".lit4")
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".lit8")
-#endif /* HAS_SBSS_SECTION */
+ || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ ".got")
+ || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
+ ".sdata1")
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
".data1"))
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
@@ -1040,6 +1021,62 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
}
}
#endif /* __sony_news && _SYSTYPE_SYSV */
+
+#if __sgi
+ /* 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);
+ }
+ }
+ }
+#endif /* __sgi */
+
/* If it is the symbol table, its st_shndx field needs to be patched. */
if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
|| NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
@@ -1099,6 +1136,16 @@ unexec (new_name, old_name, data_start, bss_start, entry_address)
nn = section.sh_info;
if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
|| !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+ ".sdata")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+ ".lit4")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+ ".lit8")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+ ".got")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
+ ".sdata1")
+ || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
".data1"))
{
ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -