This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] Make ia64 unwind sections corresponding to linkonce functions linkonce as well
- To: wilson at redhat dot com
- Subject: [PATCH] Make ia64 unwind sections corresponding to linkonce functions linkonce as well
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Tue, 1 May 2001 10:19:32 -0400
- Cc: binutils at sources dot redhat dot com
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following patch puts unwind info for .gnu.linkonce.t.* sections into
.gnu.linkonce.ia64unw{,i}.* so that the redundant copies are removed by the
linker.
In addition to this, it fixes readelf so that it prints all SHT_IA_64_UNWIND
sections, not just the last one with .IA_64.unwind_info as info section.
The EXCLUDE_FILE(*crtend.o) in the linker script is ugly, but necessary,
since apparently *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*) does not
work as described in documentation (looking at ldlang.c and ldgram.y there
is really no code to deal with it, so it acts the same as
*(.IA_64.unwind_info*) *(.gnu.linkonce.ia64unwi.*)).
I'll try to deal with it separately.
Tested with:
#include <exception>
void foo()
{
throw exception();
}
inline void bar()
{
foo();
}
int main()
{
try {
bar();
} catch (...) {};
}
compiled with -O0 (with some .xdata8 hand adjusted) - it creates exactly
the same binary as without this patch (again, with some .xdata8 hand
adjusted, though in a different way).
Ok to commit?
If this makes it in, I'll post adjusted gcc patch for .xdata8 output.
2001-05-01 Jakub Jelinek <jakub@redhat.com>
bfd/
* elfxx-ia64.c (is_unwind_section_name): Consider linkonce unwind
sections as well.
(elfNN_ia64_final_write_processing): Map .gnu.linkonce.ia64unw.FOO
to .gnu.linkonce.t.FOO text section.
binutils/
* readelf.c (process_unwind): Print all unwind sections, not just
one.
gas/
* config/tc-ia64.c (special_linkonce_name): New.
(make_unw_section): Map .gnu.linkonce.t.FOO text section into
.gnu.linkonce.ia64unw{,i}.FOO.
(ia64_elf_section_type): Handle .gnu.linkonce.ia64unw{,i}.FOO.
(dot_endp): Add comment about it.
include/
* elf/ia64.h (ELF_STRING_ia64_unwind_once): Define.
(ELF_STRING_ia64_unwind_info_once): Define.
ld/
* emulparams/elf64_ia64.sh (OTHER_READONLY_SECTIONS): Put
.gnu.linkonce.ia64unw{,i} sections into corresponding .IA_64.unwind*
output sections, make sure crtend.o's .IA_64.unwind section comes
last.
--- bfd/elfxx-ia64.c.jj Wed Feb 14 02:32:26 2001
+++ bfd/elfxx-ia64.c Tue May 1 07:39:57 2001
@@ -910,12 +910,14 @@ static inline boolean
is_unwind_section_name (name)
const char *name;
{
- size_t len1, len2;
+ size_t len1, len2, len3;
len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
- return (strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
- && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0);
+ len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
+ return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
+ && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
+ || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
}
/* Handle an IA-64 specific section when reading an object file. This
@@ -1053,6 +1055,18 @@ elfNN_ia64_final_write_processing (abfd,
else
/* .IA_64.unwindFOO -> FOO */
text_sect = bfd_get_section_by_name (abfd, sname);
+ }
+ else if (sname
+ && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
+ strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
+ {
+ /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
+ size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
+ char *once_name = alloca (len2 + strlen (sname) - len + 1);
+
+ memcpy (once_name, ".gnu.linkonce.t.", len2);
+ strcpy (once_name + len2, sname + len);
+ text_sect = bfd_get_section_by_name (abfd, once_name);
}
else
/* last resort: fall back on .text */
--- binutils/readelf.c.jj Sun Feb 11 19:48:25 2001
+++ binutils/readelf.c Tue May 1 08:32:12 2001
@@ -3372,7 +3372,7 @@ process_unwind (file)
FILE * file;
{
Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec;
- unsigned long i, addr_size;
+ unsigned long i, addr_size, unwcount = 0, unwstart = 0;
struct unw_aux_info aux;
memset (& aux, 0, sizeof (aux));
@@ -3395,40 +3395,100 @@ process_unwind (file)
(char *) aux.strtab, char *, "string table");
}
else if (sec->sh_type == SHT_IA_64_UNWIND)
- unwsec = sec;
- else if (strcmp (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info) == 0)
- {
- aux.info_size = sec->sh_size;
- aux.info_addr = sec->sh_addr;
- GET_DATA_ALLOC (sec->sh_offset, aux.info_size, aux.info,
- char *, "unwind info");
- }
+ unwcount++;
}
- if (unwsec)
+ if (!unwcount)
+ printf (_("\nThere are no unwind sections in this file.\n"));
+
+ while (unwcount-- > 0)
{
- printf (_("\nUnwind section "));
+ char *suffix;
+ size_t len, len2;
+
+ for (i = unwstart, sec = section_headers + unwstart;
+ i < elf_header.e_shnum; ++i, ++sec)
+ if (sec->sh_type == SHT_IA_64_UNWIND)
+ {
+ unwsec = sec;
+ break;
+ }
+
+ unwstart = i + 1;
+ len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
- if (string_table == NULL)
- printf ("%d", unwsec->sh_name);
+ if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once,
+ len) == 0)
+ {
+ /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */
+ len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
+ suffix = SECTION_NAME (unwsec) + len;
+ for (i = 0, sec = section_headers; i < elf_header.e_shnum;
+ ++i, ++sec)
+ if (strncmp (SECTION_NAME (sec),
+ ELF_STRING_ia64_unwind_info_once, len2) == 0
+ && strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
+ break;
+ }
else
- printf ("'%s'", SECTION_NAME (unwsec));
+ {
+ /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO
+ .IA_64.unwind or BAR -> .IA_64.unwind_info */
+ len = sizeof (ELF_STRING_ia64_unwind) - 1;
+ len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
+ suffix = "";
+ if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind,
+ len) == 0)
+ suffix = SECTION_NAME (unwsec) + len;
+ for (i = 0, sec = section_headers; i < elf_header.e_shnum;
+ ++i, ++sec)
+ if (strncmp (SECTION_NAME (sec),
+ ELF_STRING_ia64_unwind_info, len2) == 0
+ && strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
+ break;
+ }
+
+ if (i == elf_header.e_shnum)
+ {
+ printf (_("\nCould not find unwind info section for "));
- printf (_(" at offset 0x%lx contains %lu entries:\n"),
- unwsec->sh_offset, (unsigned long) (unwsec->sh_size / (3 * addr_size)));
+ if (string_table == NULL)
+ printf ("%d", unwsec->sh_name);
+ else
+ printf ("'%s'", SECTION_NAME (unwsec));
+ }
+ else
+ {
+ aux.info_size = sec->sh_size;
+ aux.info_addr = sec->sh_addr;
+ GET_DATA_ALLOC (sec->sh_offset, aux.info_size, aux.info,
+ char *, "unwind info");
- (void) slurp_ia64_unwind_table (file, & aux, unwsec);
+ printf (_("\nUnwind section "));
- if (aux.table_len > 0)
- dump_ia64_unwind (& aux);
+ if (string_table == NULL)
+ printf ("%d", unwsec->sh_name);
+ else
+ printf ("'%s'", SECTION_NAME (unwsec));
+
+ printf (_(" at offset 0x%lx contains %lu entries:\n"),
+ unwsec->sh_offset,
+ (unsigned long) (unwsec->sh_size / (3 * addr_size)));
+
+ (void) slurp_ia64_unwind_table (file, & aux, unwsec);
+
+ if (aux.table_len > 0)
+ dump_ia64_unwind (& aux);
+
+ if (aux.table)
+ free ((char *) aux.table);
+ if (aux.info)
+ free ((char *) aux.info);
+ aux.table = NULL;
+ aux.info = NULL;
+ }
}
- else
- printf (_("\nThere are no unwind sections in this file.\n"));
- if (aux.table)
- free ((char *) aux.table);
- if (aux.info)
- free ((char *) aux.info);
if (aux.symtab)
free (aux.symtab);
if (aux.strtab)
--- gas/config/tc-ia64.c.jj Wed Feb 14 02:27:23 2001
+++ gas/config/tc-ia64.c Tue May 1 07:30:36 2001
@@ -518,6 +518,11 @@ static char special_section_name[][20] =
{".IA_64.unwind"}, {".IA_64.unwind_info"}
};
+static char *special_linkonce_name[] =
+ {
+ ".gnu.linkonce.ia64unw.", ".gnu.linkonce.ia64unwi."
+ };
+
/* The best template for a particular sequence of up to three
instructions: */
#define N IA64_NUM_TYPES
@@ -842,11 +847,20 @@ static int generate_unwind_image PARAMS
#define make_unw_section_name(special, text_name, result) \
{ \
char *_prefix = special_section_name[special]; \
- size_t _prefix_len = strlen (_prefix), _text_len = strlen (text_name); \
- char *_result = alloca (_prefix_len + _text_len + 1); \
+ char *_suffix = text_name; \
+ size_t _prefix_len, _suffix_len; \
+ char *_result; \
+ if (strncmp (text_name, ".gnu.linkonce.t.", \
+ sizeof (".gnu.linkonce.t.") - 1) == 0) \
+ { \
+ _prefix = special_linkonce_name[special - SPECIAL_SECTION_UNWIND]; \
+ _suffix += sizeof (".gnu.linkonce.t.") - 1; \
+ } \
+ _prefix_len = strlen (_prefix), _suffix_len = strlen (_suffix); \
+ _result = alloca (_prefix_len + _suffix_len + 1); \
memcpy(_result, _prefix, _prefix_len); \
- memcpy(_result + _prefix_len, text_name, _text_len); \
- _result[_prefix_len + _text_len] = '\0'; \
+ memcpy(_result + _prefix_len, _suffix, _suffix_len); \
+ _result[_prefix_len + _suffix_len] = '\0'; \
result = _result; \
} \
while (0)
@@ -903,10 +917,18 @@ ia64_elf_section_type (str, len)
if (strncmp (str, ELF_STRING_ia64_unwind_info, len) == 0)
return SHT_PROGBITS;
+ len = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
+ if (strncmp (str, ELF_STRING_ia64_unwind_info_once, len) == 0)
+ return SHT_PROGBITS;
+
len = sizeof (ELF_STRING_ia64_unwind) - 1;
if (strncmp (str, ELF_STRING_ia64_unwind, len) == 0)
return SHT_IA_64_UNWIND;
+ len = sizeof (ELF_STRING_ia64_unwind_once) - 1;
+ if (strncmp (str, ELF_STRING_ia64_unwind_once, len) == 0)
+ return SHT_IA_64_UNWIND;
+
return -1;
}
@@ -3800,6 +3822,8 @@ dot_endp (dummy)
.text .IA_64.unwind
.text.foo .IA_64.unwind.text.foo
.foo .IA_64.unwind.foo
+ .gnu.linkonce.t.foo
+ .gnu.linkonce.ia64unw.foo
_info .IA_64.unwind_info gas issues error message (ditto)
_infoFOO .IA_64.unwind_infoFOO gas issues error message (ditto)
--- include/elf/ia64.h.jj Thu Nov 16 18:35:07 2000
+++ include/elf/ia64.h Tue May 1 07:25:31 2001
@@ -47,6 +47,8 @@ Foundation, Inc., 59 Temple Place - Suit
#define ELF_STRING_ia64_pltoff ".IA_64.pltoff"
#define ELF_STRING_ia64_unwind ".IA_64.unwind"
#define ELF_STRING_ia64_unwind_info ".IA_64.unwind_info"
+#define ELF_STRING_ia64_unwind_once ".gnu.linkonce.ia64unw."
+#define ELF_STRING_ia64_unwind_info_once ".gnu.linkonce.ia64unwi."
/* Bits in the sh_flags field of Elf64_Shdr: */
--- ld/emulparams/elf64_ia64.sh.jj Wed Feb 14 02:23:16 2001
+++ ld/emulparams/elf64_ia64.sh Tue May 1 09:42:28 2001
@@ -12,4 +12,4 @@ GENERATE_SHLIB_SCRIPT=yes
NOP=0x00300000010070000002000001000400 # a bundle full of nops
OTHER_GOT_SECTIONS='.IA_64.pltoff : { *(.IA_64.pltoff) }'
OTHER_PLT_RELOC_SECTIONS='.rela.IA_64.pltoff : { *(.rela.IA_64.pltoff) }'
-OTHER_READONLY_SECTIONS='.opd : { *(.opd) } .IA_64.unwind_info : { *(.IA_64.unwind_info*) } .IA_64.unwind : { *(.IA_64.unwind*) }'
+OTHER_READONLY_SECTIONS='.opd : { *(.opd) } .IA_64.unwind_info : { *(.IA_64.unwind_info*) *(.gnu.linkonce.ia64unwi.*) } .IA_64.unwind : { *(EXCLUDE_FILE(*crtend.o) .IA_64.unwind*) *(.gnu.linkonce.ia64unw.*) *(.IA_64.unwind*) }'
Jakub