aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJulian Brown <julian@codesourcery.com>2005-03-29 16:29:09 +0000
committerJulian Brown <julian@codesourcery.com>2005-03-29 16:29:09 +0000
commit84798bd6b6da79bc96633b981573ededa9727d44 (patch)
treec05aa6c561222a2dcea729fba49428fa563a1863 /gas/config
parentec72cfe589400f06810a571ce4d7f45fb6e19621 (diff)
downloadgdb-84798bd6b6da79bc96633b981573ededa9727d44.zip
gdb-84798bd6b6da79bc96633b981573ededa9727d44.tar.gz
gdb-84798bd6b6da79bc96633b981573ededa9727d44.tar.bz2
* gas/config/tc-arm.c (marked_pr_dependency): New bitmap, bit N
indicates whether personality routine index N has been output for this section. (mapping_state): tc_segment_info_data now struct not enum. (arm_elf_change_section): Likewise, and marked_pr_dependency is now handled on section change. (create_unwind_entry): Previous code to output dependency removed. (s_arm_unwind_fnend): Output dependency if it hasn't been done already for this section. * gas/config/tc-arm.h (TC_SEGMENT_INFO_TYPE): Redefined as struct arm_segment_info_type. (arm_segment_info_type): New struct. * gas/testsuite/gas/arm/unwind.d: Update expected output.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-arm.c49
-rw-r--r--gas/config/tc-arm.h8
2 files changed, 35 insertions, 22 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 19faa62..9baf888 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -83,6 +83,11 @@ static struct
unsigned sp_restored:1;
} unwind;
+/* Bit N indicates that an R_ARM_NONE relocation has been output for
+ __aeabi_unwind_cpp_prN already if set. This enables dependencies to be
+ emitted only once per section, to save unnecessary bloat. */
+static unsigned int marked_pr_dependency = 0;
+
#endif /* OBJ_ELF */
enum arm_float_abi
@@ -1347,7 +1352,7 @@ mapping_state (enum mstate state)
abort ();
}
- seg_info (now_seg)->tc_segment_info_data = state;
+ seg_info (now_seg)->tc_segment_info_data.mapstate = state;
symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
symbol_table_insert (symbolP);
@@ -1379,6 +1384,7 @@ void
arm_elf_change_section (void)
{
flagword flags;
+ segment_info_type *seginfo;
/* Link an unlinked unwind index table section to the .text section. */
if (elf_section_type (now_seg) == SHT_ARM_EXIDX
@@ -1394,7 +1400,9 @@ arm_elf_change_section (void)
if ((flags & SEC_ALLOC) == 0)
return;
- mapstate = seg_info (now_seg)->tc_segment_info_data;
+ seginfo = seg_info (now_seg);
+ mapstate = seginfo->tc_segment_info_data.mapstate;
+ marked_pr_dependency = seginfo->tc_segment_info_data.marked_pr_dependency;
}
int
@@ -14303,13 +14311,6 @@ create_unwind_entry (int have_data)
fix_new (frag_now, where, 4, unwind.personality_routine, 0, 1,
BFD_RELOC_ARM_PREL31);
- /* Indicate dependency to linker. */
- {
- char *name = "__aeabi_unwind_cpp_pr0";
- symbolS *pr = symbol_find_or_make (name);
- fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
- }
-
where += 4;
ptr += 4;
@@ -14323,24 +14324,13 @@ create_unwind_entry (int have_data)
/* Three opcodes bytes are packed into the first word. */
data = 0x80;
n = 3;
- goto emit_reloc;
+ break;
case 1:
case 2:
/* The size and first two opcode bytes go in the first word. */
data = ((0x80 + unwind.personality_index) << 8) | size;
n = 2;
- goto emit_reloc;
-
- emit_reloc:
- {
- /* Indicate dependency to linker. */
- char *name[] = { "__aeabi_unwind_cpp_pr0",
- "__aeabi_unwind_cpp_pr1",
- "__aeabi_unwind_cpp_pr2" };
- symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
- fix_new (frag_now, where, 4, pr, 0, 1, BFD_RELOC_NONE);
- }
break;
default:
@@ -14449,6 +14439,23 @@ s_arm_unwind_fnend (int ignored ATTRIBUTE_UNUSED)
fix_new (frag_now, where, 4, unwind.proc_start, 0, 1,
BFD_RELOC_ARM_PREL31);
+ /* Indicate dependency on EHABI-defined personality routines to the
+ linker, if it hasn't been done already. */
+ if (unwind.personality_index >= 0 && unwind.personality_index < 3)
+ {
+ char *name[] = { "__aeabi_unwind_cpp_pr0",
+ "__aeabi_unwind_cpp_pr1",
+ "__aeabi_unwind_cpp_pr2" };
+ if (!(marked_pr_dependency & (1 << unwind.personality_index)))
+ {
+ symbolS *pr = symbol_find_or_make (name[unwind.personality_index]);
+ fix_new (frag_now, where, 0, pr, 0, 1, BFD_RELOC_NONE);
+ marked_pr_dependency |= 1 << unwind.personality_index;
+ seg_info (now_seg)->tc_segment_info_data.marked_pr_dependency
+ = marked_pr_dependency;
+ }
+ }
+
if (val)
/* Inline exception table entry. */
md_number_to_chars (ptr + 4, val, 4);
diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h
index f205dff..e3c05b3 100644
--- a/gas/config/tc-arm.h
+++ b/gas/config/tc-arm.h
@@ -170,7 +170,7 @@ struct fix;
# define md_elf_section_type(str, len) arm_elf_section_type (str, len)
# define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
# define LOCAL_LABEL_PREFIX '.'
-# define TC_SEGMENT_INFO_TYPE enum mstate
+# define TC_SEGMENT_INFO_TYPE struct arm_segment_info_type
enum mstate
{
@@ -180,6 +180,12 @@ enum mstate
MAP_THUMB
};
+struct arm_segment_info_type
+{
+ enum mstate mapstate;
+ unsigned int marked_pr_dependency;
+};
+
/* We want .cfi_* pseudo-ops for generating unwind info. */
#define TARGET_USE_CFIPOP 1