2011-05-09 Paul Brook <paul@codesourcery.com>

bfd/
	* bfd-in.h (elf32_tic6x_fix_exidx_coverage): Add prototype.
	* bfd-in2.h: Regenerate.
	* elf32-tic6x.c: Include limits.h.
	(tic6x_unwind_edit_type, tic6x_unwind_table_edit,
	_tic6x_elf_section_data): New.
	(elf32_tic6x_section_data): Define.
	(elf32_tic6x_new_section_hook): Allocate target specific data.
	(elf32_tic6x_add_unwind_table_edit): New function.
	(get_tic6x_elf_section_data, elf32_tic6x_adjust_exidx_size,
	elf32_tic6x_insert_cantunwind_after, elf32_tic6x_add_low31,
	elf32_tic6x_copy_exidx_entry): New functions.
	(elf_backend_write_section): Define.

	ld/
	* emultempl/tic6xdsbt.em (merge_exidx_entries): New.
	(compare_output_sec_vma): New function.
	(gld${EMULATION_NAME}_after_allocation): New function.
	(OPTION_NO_MERGE_EXIDX_ENTRIES): Define.
	(PARSE_AND_LIST_OPTIONS): Add --no-merge-exidx-entries.
	(PARSE_AND_LIST_ARGS_CASES): Add OPTION_NO_MERGE_EXIDX_ENTRIES.
	(LDEMUL_AFTER_ALLOCATION): Set.
	* ld.texinfo: Document c6x --no-merge-exidx-entries.

	ld/testsuite/
	* ld-tic6x/discard-unwind.ld: New.
	* ld-tic6x/unwind.ld: New.
	* ld-tic6x/unwind-1.d: New test.
	* ld-tic6x/unwind-1.s: New test.
	* ld-tic6x/unwind-2.d: New test.
	* ld-tic6x/unwind-2.s: New test.
	* ld-tic6x/unwind-3.d: New test.
	* ld-tic6x/unwind-3.s: New test.
	* ld-tic6x/unwind-4.d: New test.
	* ld-tic6x/unwind-4.s: New test.
	* ld-tic6x/unwind-5.d: New test.
	* ld-tic6x/unwind-5.s: New test.
	* ld-tic6x/unwind-6.d: New test.
This commit is contained in:
Paul Brook 2011-05-09 13:23:27 +00:00
parent 1bce6bd86f
commit fbd9ad907d
21 changed files with 879 additions and 0 deletions

View File

@ -1,3 +1,18 @@
2011-05-09 Paul Brook <paul@codesourcery.com>
* bfd-in.h (elf32_tic6x_fix_exidx_coverage): Add prototype.
* bfd-in2.h: Regenerate.
* elf32-tic6x.c: Include limits.h.
(tic6x_unwind_edit_type, tic6x_unwind_table_edit,
_tic6x_elf_section_data): New.
(elf32_tic6x_section_data): Define.
(elf32_tic6x_new_section_hook): Allocate target specific data.
(elf32_tic6x_add_unwind_table_edit): New function.
(get_tic6x_elf_section_data, elf32_tic6x_adjust_exidx_size,
elf32_tic6x_insert_cantunwind_after, elf32_tic6x_add_low31,
elf32_tic6x_copy_exidx_entry): New functions.
(elf_backend_write_section): Define.
2011-05-09 Paul Brook <paul@codesourcery.com>
* elf32-tic6x.c (is_tic6x_elf_unwind_section_name,

View File

@ -912,6 +912,10 @@ extern bfd_boolean elf32_arm_build_stubs
extern bfd_boolean elf32_arm_fix_exidx_coverage
(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean);
/* C6x unwind section editing support. */
extern bfd_boolean elf32_tic6x_fix_exidx_coverage
(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean);
/* PowerPC @tls opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tls_transform
(unsigned int, unsigned int);

View File

@ -919,6 +919,10 @@ extern bfd_boolean elf32_arm_build_stubs
extern bfd_boolean elf32_arm_fix_exidx_coverage
(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean);
/* C6x unwind section editing support. */
extern bfd_boolean elf32_tic6x_fix_exidx_coverage
(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean);
/* PowerPC @tls opcode transform/validate. */
extern unsigned int _bfd_elf_ppc_at_tls_transform
(unsigned int, unsigned int);

View File

@ -22,6 +22,7 @@
MA 02110-1301, USA. */
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
#include "libiberty.h"
@ -75,6 +76,52 @@ struct elf32_tic6x_link_hash_entry
struct elf_dyn_relocs *dyn_relocs;
};
typedef enum
{
DELETE_EXIDX_ENTRY,
INSERT_EXIDX_CANTUNWIND_AT_END
}
tic6x_unwind_edit_type;
/* A (sorted) list of edits to apply to an unwind table. */
typedef struct tic6x_unwind_table_edit
{
tic6x_unwind_edit_type type;
/* Note: we sometimes want to insert an unwind entry corresponding to a
section different from the one we're currently writing out, so record the
(text) section this edit relates to here. */
asection *linked_section;
unsigned int index;
struct tic6x_unwind_table_edit *next;
}
tic6x_unwind_table_edit;
typedef struct _tic6x_elf_section_data
{
/* Information about mapping symbols. */
struct bfd_elf_section_data elf;
/* Information about unwind tables. */
union
{
/* Unwind info attached to a text section. */
struct
{
asection *tic6x_exidx_sec;
} text;
/* Unwind info attached to an .c6xabi.exidx section. */
struct
{
tic6x_unwind_table_edit *unwind_edit_list;
tic6x_unwind_table_edit *unwind_edit_tail;
} exidx;
} u;
}
_tic6x_elf_section_data;
#define elf32_tic6x_section_data(sec) \
((_tic6x_elf_section_data *) elf_section_data (sec))
struct elf32_tic6x_obj_tdata
{
struct elf_obj_tdata root;
@ -2120,6 +2167,18 @@ elf32_tic6x_new_section_hook (bfd *abfd, asection *sec)
{
bfd_boolean ret;
/* Allocate target specific section data. */
if (!sec->used_by_bfd)
{
_tic6x_elf_section_data *sdata;
bfd_size_type amt = sizeof (*sdata);
sdata = (_tic6x_elf_section_data *) bfd_zalloc (abfd, amt);
if (sdata == NULL)
return FALSE;
sec->used_by_bfd = sdata;
}
ret = _bfd_elf_new_section_hook (abfd, sec);
sec->use_rela_p = elf32_tic6x_tdata (abfd)->use_rela_p;
@ -3977,6 +4036,409 @@ elf32_tic6x_copy_private_data (bfd * ibfd, bfd * obfd)
return TRUE;
}
/* Add a new unwind edit to the list described by HEAD, TAIL. If TINDEX is zero,
adds the edit to the start of the list. (The list must be built in order of
ascending TINDEX: the function's callers are primarily responsible for
maintaining that condition). */
static void
elf32_tic6x_add_unwind_table_edit (tic6x_unwind_table_edit **head,
tic6x_unwind_table_edit **tail,
tic6x_unwind_edit_type type,
asection *linked_section,
unsigned int tindex)
{
tic6x_unwind_table_edit *new_edit = (tic6x_unwind_table_edit *)
xmalloc (sizeof (tic6x_unwind_table_edit));
new_edit->type = type;
new_edit->linked_section = linked_section;
new_edit->index = tindex;
if (tindex > 0)
{
new_edit->next = NULL;
if (*tail)
(*tail)->next = new_edit;
(*tail) = new_edit;
if (!*head)
(*head) = new_edit;
}
else
{
new_edit->next = *head;
if (!*tail)
*tail = new_edit;
*head = new_edit;
}
}
static _tic6x_elf_section_data *
get_tic6x_elf_section_data (asection * sec)
{
if (sec && sec->owner && is_tic6x_elf (sec->owner))
return elf32_tic6x_section_data (sec);
else
return NULL;
}
/* Increase the size of EXIDX_SEC by ADJUST bytes. ADJUST must be negative. */
static void
elf32_tic6x_adjust_exidx_size (asection *exidx_sec, int adjust)
{
asection *out_sec;
if (!exidx_sec->rawsize)
exidx_sec->rawsize = exidx_sec->size;
bfd_set_section_size (exidx_sec->owner, exidx_sec, exidx_sec->size + adjust);
out_sec = exidx_sec->output_section;
/* Adjust size of output section. */
bfd_set_section_size (out_sec->owner, out_sec, out_sec->size +adjust);
}
/* Insert an EXIDX_CANTUNWIND marker at the end of a section. */
static void
elf32_tic6x_insert_cantunwind_after (asection *text_sec, asection *exidx_sec)
{
struct _tic6x_elf_section_data *exidx_data;
exidx_data = get_tic6x_elf_section_data (exidx_sec);
elf32_tic6x_add_unwind_table_edit (
&exidx_data->u.exidx.unwind_edit_list,
&exidx_data->u.exidx.unwind_edit_tail,
INSERT_EXIDX_CANTUNWIND_AT_END, text_sec, UINT_MAX);
elf32_tic6x_adjust_exidx_size (exidx_sec, 8);
}
/* Scan .cx6abi.exidx tables, and create a list describing edits which
should be made to those tables, such that:
1. Regions without unwind data are marked with EXIDX_CANTUNWIND entries.
2. Duplicate entries are merged together (EXIDX_CANTUNWIND, or unwind
codes which have been inlined into the index).
If MERGE_EXIDX_ENTRIES is false, duplicate entries are not merged.
The edits are applied when the tables are written
(in elf32_tic6x_write_section).
*/
bfd_boolean
elf32_tic6x_fix_exidx_coverage (asection **text_section_order,
unsigned int num_text_sections,
struct bfd_link_info *info,
bfd_boolean merge_exidx_entries)
{
bfd *inp;
unsigned int last_second_word = 0, i;
asection *last_exidx_sec = NULL;
asection *last_text_sec = NULL;
int last_unwind_type = -1;
/* Walk over all EXIDX sections, and create backlinks from the corrsponding
text sections. */
for (inp = info->input_bfds; inp != NULL; inp = inp->link_next)
{
asection *sec;
for (sec = inp->sections; sec != NULL; sec = sec->next)
{
struct bfd_elf_section_data *elf_sec = elf_section_data (sec);
Elf_Internal_Shdr *hdr = &elf_sec->this_hdr;
if (!hdr || hdr->sh_type != SHT_C6000_UNWIND)
continue;
if (elf_sec->linked_to)
{
Elf_Internal_Shdr *linked_hdr
= &elf_section_data (elf_sec->linked_to)->this_hdr;
struct _tic6x_elf_section_data *linked_sec_tic6x_data
= get_tic6x_elf_section_data (linked_hdr->bfd_section);
if (linked_sec_tic6x_data == NULL)
continue;
/* Link this .c6xabi.exidx section back from the
text section it describes. */
linked_sec_tic6x_data->u.text.tic6x_exidx_sec = sec;
}
}
}
/* Walk all text sections in order of increasing VMA. Eilminate duplicate
index table entries (EXIDX_CANTUNWIND and inlined unwind opcodes),
and add EXIDX_CANTUNWIND entries for sections with no unwind table data. */
for (i = 0; i < num_text_sections; i++)
{
asection *sec = text_section_order[i];
asection *exidx_sec;
struct _tic6x_elf_section_data *tic6x_data
= get_tic6x_elf_section_data (sec);
struct _tic6x_elf_section_data *exidx_data;
bfd_byte *contents = NULL;
int deleted_exidx_bytes = 0;
bfd_vma j;
tic6x_unwind_table_edit *unwind_edit_head = NULL;
tic6x_unwind_table_edit *unwind_edit_tail = NULL;
Elf_Internal_Shdr *hdr;
bfd *ibfd;
if (tic6x_data == NULL)
continue;
exidx_sec = tic6x_data->u.text.tic6x_exidx_sec;
if (exidx_sec == NULL)
{
/* Section has no unwind data. */
if (last_unwind_type == 0 || !last_exidx_sec)
continue;
/* Ignore zero sized sections. */
if (sec->size == 0)
continue;
elf32_tic6x_insert_cantunwind_after (last_text_sec, last_exidx_sec);
last_unwind_type = 0;
continue;
}
/* Skip /DISCARD/ sections. */
if (bfd_is_abs_section (exidx_sec->output_section))
continue;
hdr = &elf_section_data (exidx_sec)->this_hdr;
if (hdr->sh_type != SHT_C6000_UNWIND)
continue;
exidx_data = get_tic6x_elf_section_data (exidx_sec);
if (exidx_data == NULL)
continue;
ibfd = exidx_sec->owner;
if (hdr->contents != NULL)
contents = hdr->contents;
else if (! bfd_malloc_and_get_section (ibfd, exidx_sec, &contents))
/* An error? */
continue;
for (j = 0; j < hdr->sh_size; j += 8)
{
unsigned int second_word = bfd_get_32 (ibfd, contents + j + 4);
int unwind_type;
int elide = 0;
/* An EXIDX_CANTUNWIND entry. */
if (second_word == 1)
{
if (last_unwind_type == 0)
elide = 1;
unwind_type = 0;
}
/* Inlined unwinding data. Merge if equal to previous. */
else if ((second_word & 0x80000000) != 0)
{
if (merge_exidx_entries
&& last_second_word == second_word
&& last_unwind_type == 1)
elide = 1;
unwind_type = 1;
last_second_word = second_word;
}
/* Normal table entry. In theory we could merge these too,
but duplicate entries are likely to be much less common. */
else
unwind_type = 2;
if (elide)
{
elf32_tic6x_add_unwind_table_edit (&unwind_edit_head,
&unwind_edit_tail, DELETE_EXIDX_ENTRY, NULL, j / 8);
deleted_exidx_bytes += 8;
}
last_unwind_type = unwind_type;
}
/* Free contents if we allocated it ourselves. */
if (contents != hdr->contents)
free (contents);
/* Record edits to be applied later (in elf32_tic6x_write_section). */
exidx_data->u.exidx.unwind_edit_list = unwind_edit_head;
exidx_data->u.exidx.unwind_edit_tail = unwind_edit_tail;
if (deleted_exidx_bytes > 0)
elf32_tic6x_adjust_exidx_size (exidx_sec, -deleted_exidx_bytes);
last_exidx_sec = exidx_sec;
last_text_sec = sec;
}
/* Add terminating CANTUNWIND entry. */
if (last_exidx_sec && last_unwind_type != 0)
elf32_tic6x_insert_cantunwind_after (last_text_sec, last_exidx_sec);
return TRUE;
}
/* Add ADDEND to lower 31 bits of VAL, leaving other bits unmodified. */
static unsigned long
elf32_tic6x_add_low31 (unsigned long val, bfd_vma addend)
{
return (val & ~0x7ffffffful) | ((val + addend) & 0x7ffffffful);
}
/* Copy an .c6xabi.exidx table entry, adding OFFSET to (applied) PREL31
relocations. OFFSET is in bytes, and will be scaled before encoding. */
static void
elf32_tic6x_copy_exidx_entry (bfd *output_bfd, bfd_byte *to, bfd_byte *from,
bfd_vma offset)
{
unsigned long first_word = bfd_get_32 (output_bfd, from);
unsigned long second_word = bfd_get_32 (output_bfd, from + 4);
offset >>= 1;
/* High bit of first word is supposed to be zero. */
if ((first_word & 0x80000000ul) == 0)
first_word = elf32_tic6x_add_low31 (first_word, offset);
/* If the high bit of the first word is clear, and the bit pattern is not 0x1
(EXIDX_CANTUNWIND), this is an offset to an .c6xabi.extab entry. */
if ((second_word != 0x1) && ((second_word & 0x80000000ul) == 0))
second_word = elf32_tic6x_add_low31 (second_word, offset);
bfd_put_32 (output_bfd, first_word, to);
bfd_put_32 (output_bfd, second_word, to + 4);
}
/* Do the actual mangling of exception index tables. */
static bfd_boolean
elf32_tic6x_write_section (bfd *output_bfd,
struct bfd_link_info *link_info,
asection *sec,
bfd_byte *contents)
{
_tic6x_elf_section_data *tic6x_data;
struct elf32_tic6x_link_hash_table *globals
= elf32_tic6x_hash_table (link_info);
bfd_vma offset = sec->output_section->vma + sec->output_offset;
if (globals == NULL)
return FALSE;
/* If this section has not been allocated an _tic6x_elf_section_data
structure then we cannot record anything. */
tic6x_data = get_tic6x_elf_section_data (sec);
if (tic6x_data == NULL)
return FALSE;
if (tic6x_data->elf.this_hdr.sh_type != SHT_C6000_UNWIND)
return FALSE;
tic6x_unwind_table_edit *edit_node
= tic6x_data->u.exidx.unwind_edit_list;
/* Now, sec->size is the size of the section we will write. The original
size (before we merged duplicate entries and inserted EXIDX_CANTUNWIND
markers) was sec->rawsize. (This isn't the case if we perform no
edits, then rawsize will be zero and we should use size). */
bfd_byte *edited_contents = (bfd_byte *) bfd_malloc (sec->size);
unsigned int input_size = sec->rawsize ? sec->rawsize : sec->size;
unsigned int in_index, out_index;
bfd_vma add_to_offsets = 0;
for (in_index = 0, out_index = 0; in_index * 8 < input_size || edit_node;)
{
if (edit_node)
{
unsigned int edit_index = edit_node->index;
if (in_index < edit_index && in_index * 8 < input_size)
{
elf32_tic6x_copy_exidx_entry (output_bfd,
edited_contents + out_index * 8,
contents + in_index * 8, add_to_offsets);
out_index++;
in_index++;
}
else if (in_index == edit_index
|| (in_index * 8 >= input_size
&& edit_index == UINT_MAX))
{
switch (edit_node->type)
{
case DELETE_EXIDX_ENTRY:
in_index++;
add_to_offsets += 8;
break;
case INSERT_EXIDX_CANTUNWIND_AT_END:
{
asection *text_sec = edit_node->linked_section;
bfd_vma text_offset = text_sec->output_section->vma
+ text_sec->output_offset
+ text_sec->size;
bfd_vma exidx_offset = offset + out_index * 8;
unsigned long prel31_offset;
/* Note: this is meant to be equivalent to an
R_C6000_PREL31 relocation. These synthetic
EXIDX_CANTUNWIND markers are not relocated by the
usual BFD method. */
prel31_offset = ((text_offset - exidx_offset) >> 1)
& 0x7ffffffful;
/* First address we can't unwind. */
bfd_put_32 (output_bfd, prel31_offset,
&edited_contents[out_index * 8]);
/* Code for EXIDX_CANTUNWIND. */
bfd_put_32 (output_bfd, 0x1,
&edited_contents[out_index * 8 + 4]);
out_index++;
add_to_offsets -= 8;
}
break;
}
edit_node = edit_node->next;
}
}
else
{
/* No more edits, copy remaining entries verbatim. */
elf32_tic6x_copy_exidx_entry (output_bfd,
edited_contents + out_index * 8,
contents + in_index * 8, add_to_offsets);
out_index++;
in_index++;
}
}
if (!(sec->flags & SEC_EXCLUDE) && !(sec->flags & SEC_NEVER_LOAD))
bfd_set_section_contents (output_bfd, sec->output_section,
edited_contents,
(file_ptr) sec->output_offset, sec->size);
return TRUE;
}
#define TARGET_LITTLE_SYM bfd_elf32_tic6x_le_vec
#define TARGET_LITTLE_NAME "elf32-tic6x-le"
#define TARGET_BIG_SYM bfd_elf32_tic6x_be_vec
@ -4036,6 +4498,7 @@ elf32_tic6x_copy_private_data (bfd * ibfd, bfd * obfd)
elf32_tic6x_finish_dynamic_sections
#define bfd_elf32_bfd_final_link \
elf32_tic6x_final_link
#define elf_backend_write_section elf32_tic6x_write_section
#define elf_info_to_howto elf32_tic6x_info_to_howto
#define elf_info_to_howto_rel elf32_tic6x_info_to_howto_rel

View File

@ -1,3 +1,14 @@
2011-05-09 Paul Brook <paul@codesourcery.com>
* emultempl/tic6xdsbt.em (merge_exidx_entries): New.
(compare_output_sec_vma): New function.
(gld${EMULATION_NAME}_after_allocation): New function.
(OPTION_NO_MERGE_EXIDX_ENTRIES): Define.
(PARSE_AND_LIST_OPTIONS): Add --no-merge-exidx-entries.
(PARSE_AND_LIST_ARGS_CASES): Add OPTION_NO_MERGE_EXIDX_ENTRIES.
(LDEMUL_AFTER_ALLOCATION): Set.
* ld.texinfo: Document c6x --no-merge-exidx-entries.
2011-05-07 Dave Korn <dave.korn.cygwin@gmail.com>
PR ld/12365

View File

@ -31,6 +31,8 @@ static struct elf32_tic6x_params params =
0, 64
};
static int merge_exidx_entries = -1;
static int
is_tic6x_target (void)
{
@ -58,6 +60,92 @@ tic6x_after_open (void)
gld${EMULATION_NAME}_after_open ();
}
static int
compare_output_sec_vma (const void *a, const void *b)
{
asection *asec = *(asection **) a, *bsec = *(asection **) b;
asection *aout = asec->output_section, *bout = bsec->output_section;
bfd_vma avma, bvma;
/* If there's no output section for some reason, compare equal. */
if (!aout || !bout)
return 0;
avma = aout->vma + asec->output_offset;
bvma = bout->vma + bsec->output_offset;
if (avma > bvma)
return 1;
else if (avma < bvma)
return -1;
return 0;
}
static void
gld${EMULATION_NAME}_after_allocation (void)
{
int layout_changed = 0;
if (!link_info.relocatable)
{
/* Build a sorted list of input text sections, then use that to process
the unwind table index. */
unsigned int list_size = 10;
asection **sec_list = (asection **)
xmalloc (list_size * sizeof (asection *));
unsigned int sec_count = 0;
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
bfd *abfd = is->the_bfd;
asection *sec;
if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
continue;
for (sec = abfd->sections; sec != NULL; sec = sec->next)
{
asection *out_sec = sec->output_section;
if (out_sec
&& elf_section_data (sec)
&& elf_section_type (sec) == SHT_PROGBITS
&& (elf_section_flags (sec) & SHF_EXECINSTR) != 0
&& (sec->flags & SEC_EXCLUDE) == 0
&& sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS
&& out_sec != bfd_abs_section_ptr)
{
if (sec_count == list_size)
{
list_size *= 2;
sec_list = (asection **)
xrealloc (sec_list, list_size * sizeof (asection *));
}
sec_list[sec_count++] = sec;
}
}
}
qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info,
merge_exidx_entries))
layout_changed = 1;
free (sec_list);
}
/* bfd_elf32_discard_info just plays with debugging sections,
ie. doesn't affect any code, so we can delay resizing the
sections. */
if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
layout_changed = 1;
gld${EMULATION_NAME}_map_segments (layout_changed);
}
EOF
# This code gets inserted into the generic elf32.sc linker script
@ -65,11 +153,13 @@ EOF
PARSE_AND_LIST_PROLOGUE='
#define OPTION_DSBT_INDEX 300
#define OPTION_DSBT_SIZE 301
#define OPTION_NO_MERGE_EXIDX_ENTRIES 302
'
PARSE_AND_LIST_LONGOPTS='
{"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX},
{"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE},
{ "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
'
PARSE_AND_LIST_OPTIONS='
@ -77,6 +167,7 @@ PARSE_AND_LIST_OPTIONS='
fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n"));
fprintf (file, _(" --dsbt-size <index>\n"));
fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n"));
fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n"));
'
PARSE_AND_LIST_ARGS_CASES='
@ -100,6 +191,9 @@ PARSE_AND_LIST_ARGS_CASES='
einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg);
}
break;
case OPTION_NO_MERGE_EXIDX_ENTRIES:
merge_exidx_entries = 0;
'
LDEMUL_AFTER_OPEN=tic6x_after_open
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation

View File

@ -2637,6 +2637,10 @@ to @var{index}. The default is 0, which is appropriate for generating
executables. If a shared library is generated with a DSBT index of 0, the
@code{R_C6000_DSBT_INDEX} relocs are copied into the output file.
@kindex --no-merge-exidx-entries
The @samp{--no-merge-exidx-entries} switch disables the merging of adjacent
exidx entries in frame unwind info.
@end table
@c man end

View File

@ -1,3 +1,19 @@
2011-05-09 Paul Brook <paul@codesourcery.com>
* ld-tic6x/discard-unwind.ld: New.
* ld-tic6x/unwind.ld: New.
* ld-tic6x/unwind-1.d: New test.
* ld-tic6x/unwind-1.s: New test.
* ld-tic6x/unwind-2.d: New test.
* ld-tic6x/unwind-2.s: New test.
* ld-tic6x/unwind-3.d: New test.
* ld-tic6x/unwind-3.s: New test.
* ld-tic6x/unwind-4.d: New test.
* ld-tic6x/unwind-4.s: New test.
* ld-tic6x/unwind-5.d: New test.
* ld-tic6x/unwind-5.s: New test.
* ld-tic6x/unwind-6.d: New test.
2011-05-07 Dave Korn <dave.korn.cygwin@gmail.com>
PR ld/12365

View File

@ -0,0 +1,15 @@
/* Script for unwinding ld tests */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x8000;
.text :
{
*(.before)
*(.text)
*(.after)
*(.c6xabi.extab*)
} =0
/DISCARD/ : { *(.c6xabi.exidx*) }
.c6xabi.attribues 0 : { *(.c6xabi.atttributes) }
}

View File

@ -0,0 +1,10 @@
#ld: -T unwind.ld
#objdump: -s
.*: file format.*
#...
Contents of section .c6xabi.exidx:
9000 (00f8ff7f 07020083 1cf8ff7f 01000000|7ffff800 83000207 7ffff81c 00000001) .*
Contents of section .far:
#...

View File

@ -0,0 +1,25 @@
.cfi_sections .c6xabi.exidx
.text
.global _start
.type _start, %function
_start:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
# Section with no unwinding information.
# Linker should insert a cantunwind entry.
.section .after, "xa"
.global __c6xabi_unwind_cpp_pr3
.type __c6xabi_unwind_cpp_pr3, %function
__c6xabi_unwind_cpp_pr3:
nop
.p2align 6
.section .far
.word 0

View File

@ -0,0 +1,10 @@
#ld: -T unwind.ld
#objdump: -s
.*: file format.*
#...
Contents of section .c6xabi.exidx:
9000 (00f8ff7f 07020083 1cf8ff7f 01000000|7ffff800 83000207 7ffff81c 00000001) .*
Contents of section .far:
#...

View File

@ -0,0 +1,23 @@
.cfi_sections .c6xabi.exidx
.text
.global __c6xabi_unwind_cpp_pr3
.type __c6xabi_unwind_cpp_pr3, %function
__c6xabi_unwind_cpp_pr3:
.global _start
.type _start, %function
_start:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
# last text section has unwind information. Linker should append a
# terminating cantunwind entry.
.section .far
.word 0

View File

@ -0,0 +1,11 @@
#ld: -T unwind.ld
#objdump: -s
.*: file format.*
#...
Contents of section .c6xabi.exidx:
9000 (00f8ff7f 07020083 1cf8ff7f 01000000|7ffff800 83000207 7ffff81c 00000001) .*
9010 (38f8ff7f 07040083 54f8ff7f 01000000|7ffff838 82000407 7ffff854 00000001) .*
Contents of section .far:
#...

View File

@ -0,0 +1,39 @@
.cfi_sections .c6xabi.exidx
.text
# section without unwind info
.global _start
.type _start, %function
_start:
b .s2 _before
nop 5
.p2align 6
# Section that will be placed first
.section .before, "xa"
.type _before, %function
_before:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
# section that will be placed last
.section .after, "xa"
.global __c6xabi_unwind_cpp_pr3
.type __c6xabi_unwind_cpp_pr3, %function
__c6xabi_unwind_cpp_pr3:
.cfi_startproc
.cfi_offset B10, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
.section .far
.word 0

View File

@ -0,0 +1,11 @@
#ld: -T unwind.ld
#objdump: -s
.*: file format.*
#...
Contents of section .c6xabi.exidx:
9000 (00f8ff7f 07020083 1cf8ff7f 7af8ff7f|7ffff800 83000207 7ffff81c 7ffff87a) .*
9010 (38f8ff7f 07020083 56f8ff7f 01000000|7ffff838 83000207 7ffff856 00000001) .*
Contents of section .far:
#...

View File

@ -0,0 +1,68 @@
.cfi_sections .c6xabi.exidx
.text
# out of line table entry
.global _start
.type _start, %function
_start:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.handlerdata
.word 0
.endp
# entry that can be merged
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
# Section that will be placed first
.section .before, "xa"
.type _before, %function
_before:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp
# section that will be placed last
.section .after, "xa"
.global __c6xabi_unwind_cpp_pr3
.type __c6xabi_unwind_cpp_pr3, %function
__c6xabi_unwind_cpp_pr3:
# entry that can be merged
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.cfi_endproc
.personalityindex 3
.endp
# final function is cantunwind, so output table size is smaller
# than sum of input sections
.global foo
.type foo, %function
foo:
.cfi_startproc
nop
.p2align 6
.cfi_endproc
.cantunwind
.endp
.section .far
.word 0

View File

@ -0,0 +1,7 @@
#ld: -T discard-unwind.ld
#objdump: -s
.*: file format.*
# Check we don't crash when discarding unwind info.
#...

View File

@ -0,0 +1,16 @@
.cfi_sections .c6xabi.exidx
.text
.global __c6xabi_unwind_cpp_pr3
.type __c6xabi_unwind_cpp_pr3, %function
__c6xabi_unwind_cpp_pr3:
.global _start
.type _start, %function
_start:
.cfi_startproc
.cfi_offset B3, 0
.cfi_def_cfa_offset 8
nop
.p2align 6
.cfi_endproc
.personalityindex 3
.endp

View File

@ -0,0 +1,13 @@
#ld: -T unwind.ld
#source unwind-4.s
#as: -mgenerate-rel
#objdump: -s
.*: file format.*
#...
Contents of section .c6xabi.exidx:
9000 (00f8ff7f 07020083 1cf8ff7f 7af8ff7f|7ffff800 83000207 7ffff81c 7ffff87a) .*
9010 (38f8ff7f 07020083 56f8ff7f 01000000|7ffff838 83000207 7ffff856 00000001) .*
Contents of section .far:
#...

View File

@ -0,0 +1,20 @@
/* Script for unwinding ld tests */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x8000;
.text :
{
*(.before)
*(.text)
*(.after)
*(.c6xabi.extab*)
} =0
. = 0x9000;
.c6xabi.exidx : { *(.c6xabi.exidx*) }
. = 0xa000;
.got : { *(.got) *(.got.plt)}
. = 0x12340000;
.far : { *(.far) }
.c6xabi.attribues 0 : { *(.c6xabi.atttributes) }
}