2004-05-04 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-ia64.c (make_unw_section_name): Removed. (start_unwind_section): New function. (generate_unwind_image): Take const segT instead of const char *. (dot_handlerdata): Adjusted. (dot_endp): Likewise.
This commit is contained in:
parent
58a9656eb6
commit
2d6ed997cf
@ -1,3 +1,12 @@
|
|||||||
|
2004-05-04 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
|
* config/tc-ia64.c (make_unw_section_name): Removed.
|
||||||
|
(start_unwind_section): New function.
|
||||||
|
(generate_unwind_image): Take const segT instead of const
|
||||||
|
char *.
|
||||||
|
(dot_handlerdata): Adjusted.
|
||||||
|
(dot_endp): Likewise.
|
||||||
|
|
||||||
2004-05-02 H.J. Lu <hongjiu.lu@intel.com>
|
2004-05-02 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* config/obj-elf.c (obj_elf_change_section): Allow the
|
* config/obj-elf.c (obj_elf_change_section): Allow the
|
||||||
|
@ -571,11 +571,6 @@ static char special_section_name[][20] =
|
|||||||
{".init_array"}, {".fini_array"}
|
{".init_array"}, {".fini_array"}
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *special_linkonce_name[] =
|
|
||||||
{
|
|
||||||
".gnu.linkonce.ia64unw.", ".gnu.linkonce.ia64unwi."
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The best template for a particular sequence of up to three
|
/* The best template for a particular sequence of up to three
|
||||||
instructions: */
|
instructions: */
|
||||||
#define N IA64_NUM_TYPES
|
#define N IA64_NUM_TYPES
|
||||||
@ -908,36 +903,10 @@ static unw_rec_list *optimize_unw_records PARAMS ((unw_rec_list *));
|
|||||||
static void fixup_unw_records PARAMS ((unw_rec_list *, int));
|
static void fixup_unw_records PARAMS ((unw_rec_list *, int));
|
||||||
static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
|
static int convert_expr_to_ab_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
|
||||||
static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
|
static int convert_expr_to_xy_reg PARAMS ((expressionS *, unsigned int *, unsigned int *));
|
||||||
static void generate_unwind_image PARAMS ((const char *));
|
|
||||||
static unsigned int get_saved_prologue_count PARAMS ((unsigned long));
|
static unsigned int get_saved_prologue_count PARAMS ((unsigned long));
|
||||||
static void save_prologue_count PARAMS ((unsigned long, unsigned int));
|
static void save_prologue_count PARAMS ((unsigned long, unsigned int));
|
||||||
static void free_saved_prologue_counts PARAMS ((void));
|
static void free_saved_prologue_counts PARAMS ((void));
|
||||||
|
|
||||||
/* Build the unwind section name by appending the (possibly stripped)
|
|
||||||
text section NAME to the unwind PREFIX. The resulting string
|
|
||||||
pointer is assigned to RESULT. The string is allocated on the
|
|
||||||
stack, so this must be a macro... */
|
|
||||||
#define make_unw_section_name(special, text_name, result) \
|
|
||||||
{ \
|
|
||||||
const char *_prefix = special_section_name[special]; \
|
|
||||||
const 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, _suffix, _suffix_len); \
|
|
||||||
_result[_prefix_len + _suffix_len] = '\0'; \
|
|
||||||
result = _result; \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
/* Determine if application register REGNUM resides in the integer
|
/* Determine if application register REGNUM resides in the integer
|
||||||
unit (as opposed to the memory unit). */
|
unit (as opposed to the memory unit). */
|
||||||
static int
|
static int
|
||||||
@ -3315,9 +3284,122 @@ dot_restorereg_p (dummy)
|
|||||||
add_unwind_entry (output_spill_reg_p (ab, reg, 0, 0, qp));
|
add_unwind_entry (output_spill_reg_p (ab, reg, 0, 0, qp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *special_linkonce_name[] =
|
||||||
|
{
|
||||||
|
".gnu.linkonce.ia64unw.", ".gnu.linkonce.ia64unwi."
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
generate_unwind_image (text_name)
|
start_unwind_section (const segT text_seg, int sec_index)
|
||||||
const char *text_name;
|
{
|
||||||
|
/*
|
||||||
|
Use a slightly ugly scheme to derive the unwind section names from
|
||||||
|
the text section name:
|
||||||
|
|
||||||
|
text sect. unwind table sect.
|
||||||
|
name: name: comments:
|
||||||
|
---------- ----------------- --------------------------------
|
||||||
|
.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)
|
||||||
|
|
||||||
|
This mapping is done so that:
|
||||||
|
|
||||||
|
(a) An object file with unwind info only in .text will use
|
||||||
|
unwind section names .IA_64.unwind and .IA_64.unwind_info.
|
||||||
|
This follows the letter of the ABI and also ensures backwards
|
||||||
|
compatibility with older toolchains.
|
||||||
|
|
||||||
|
(b) An object file with unwind info in multiple text sections
|
||||||
|
will use separate unwind sections for each text section.
|
||||||
|
This allows us to properly set the "sh_info" and "sh_link"
|
||||||
|
fields in SHT_IA_64_UNWIND as required by the ABI and also
|
||||||
|
lets GNU ld support programs with multiple segments
|
||||||
|
containing unwind info (as might be the case for certain
|
||||||
|
embedded applications).
|
||||||
|
|
||||||
|
(c) An error is issued if there would be a name clash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *text_name, *sec_text_name;
|
||||||
|
char *sec_name;
|
||||||
|
const char *prefix = special_section_name [sec_index];
|
||||||
|
const char *suffix;
|
||||||
|
size_t prefix_len, suffix_len, sec_name_len;
|
||||||
|
|
||||||
|
sec_text_name = segment_name (text_seg);
|
||||||
|
text_name = sec_text_name;
|
||||||
|
if (strncmp (text_name, "_info", 5) == 0)
|
||||||
|
{
|
||||||
|
as_bad ("Illegal section name `%s' (causes unwind section name clash)",
|
||||||
|
text_name);
|
||||||
|
ignore_rest_of_line ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp (text_name, ".text") == 0)
|
||||||
|
text_name = "";
|
||||||
|
|
||||||
|
/* Build the unwind section name by appending the (possibly stripped)
|
||||||
|
text section name to the unwind prefix. */
|
||||||
|
suffix = text_name;
|
||||||
|
if (strncmp (text_name, ".gnu.linkonce.t.",
|
||||||
|
sizeof (".gnu.linkonce.t.") - 1) == 0)
|
||||||
|
{
|
||||||
|
prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
|
||||||
|
suffix += sizeof (".gnu.linkonce.t.") - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix_len = strlen (prefix);
|
||||||
|
suffix_len = strlen (suffix);
|
||||||
|
sec_name_len = prefix_len + suffix_len;
|
||||||
|
sec_name = alloca (sec_name_len + 1);
|
||||||
|
memcpy (sec_name, prefix, prefix_len);
|
||||||
|
memcpy (sec_name + prefix_len, suffix, suffix_len);
|
||||||
|
sec_name [sec_name_len] = '\0';
|
||||||
|
|
||||||
|
/* Handle COMDAT group. */
|
||||||
|
if (suffix == text_name && (text_seg->flags & SEC_LINK_ONCE) != 0)
|
||||||
|
{
|
||||||
|
char *section;
|
||||||
|
size_t len, group_name_len;
|
||||||
|
const char *group_name = elf_group_name (text_seg);
|
||||||
|
|
||||||
|
if (group_name == NULL)
|
||||||
|
{
|
||||||
|
as_bad ("Group section `%s' has no group signature",
|
||||||
|
sec_text_name);
|
||||||
|
ignore_rest_of_line ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* We have to construct a fake section directive. */
|
||||||
|
group_name_len = strlen (group_name);
|
||||||
|
len = (sec_name_len
|
||||||
|
+ 16 /* ,"aG",@progbits, */
|
||||||
|
+ group_name_len /* ,group_name */
|
||||||
|
+ 7); /* ,comdat */
|
||||||
|
|
||||||
|
section = alloca (len + 1);
|
||||||
|
memcpy (section, sec_name, sec_name_len);
|
||||||
|
memcpy (section + sec_name_len, ",\"aG\",@progbits,", 16);
|
||||||
|
memcpy (section + sec_name_len + 16, group_name, group_name_len);
|
||||||
|
memcpy (section + len - 7, ",comdat", 7);
|
||||||
|
section [len] = '\0';
|
||||||
|
set_section (section);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_section (sec_name);
|
||||||
|
bfd_set_section_flags (stdoutput, now_seg,
|
||||||
|
SEC_LOAD | SEC_ALLOC | SEC_READONLY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
generate_unwind_image (const segT text_seg)
|
||||||
{
|
{
|
||||||
int size, pad;
|
int size, pad;
|
||||||
unw_rec_list *list;
|
unw_rec_list *list;
|
||||||
@ -3350,14 +3432,10 @@ generate_unwind_image (text_name)
|
|||||||
/* If there are unwind records, switch sections, and output the info. */
|
/* If there are unwind records, switch sections, and output the info. */
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
{
|
{
|
||||||
char *sec_name;
|
|
||||||
expressionS exp;
|
expressionS exp;
|
||||||
bfd_reloc_code_real_type reloc;
|
bfd_reloc_code_real_type reloc;
|
||||||
|
|
||||||
make_unw_section_name (SPECIAL_SECTION_UNWIND_INFO, text_name, sec_name);
|
start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
|
||||||
set_section (sec_name);
|
|
||||||
bfd_set_section_flags (stdoutput, now_seg,
|
|
||||||
SEC_LOAD | SEC_ALLOC | SEC_READONLY);
|
|
||||||
|
|
||||||
/* Make sure the section has 4 byte alignment for ILP32 and
|
/* Make sure the section has 4 byte alignment for ILP32 and
|
||||||
8 byte alignment for LP64. */
|
8 byte alignment for LP64. */
|
||||||
@ -3406,13 +3484,6 @@ static void
|
|||||||
dot_handlerdata (dummy)
|
dot_handlerdata (dummy)
|
||||||
int dummy ATTRIBUTE_UNUSED;
|
int dummy ATTRIBUTE_UNUSED;
|
||||||
{
|
{
|
||||||
const char *text_name = segment_name (now_seg);
|
|
||||||
|
|
||||||
/* If text section name starts with ".text" (which it should),
|
|
||||||
strip this prefix off. */
|
|
||||||
if (strcmp (text_name, ".text") == 0)
|
|
||||||
text_name = "";
|
|
||||||
|
|
||||||
unwind.force_unwind_entry = 1;
|
unwind.force_unwind_entry = 1;
|
||||||
|
|
||||||
/* Remember which segment we're in so we can switch back after .endp */
|
/* Remember which segment we're in so we can switch back after .endp */
|
||||||
@ -3422,7 +3493,7 @@ dot_handlerdata (dummy)
|
|||||||
/* Generate unwind info into unwind-info section and then leave that
|
/* Generate unwind info into unwind-info section and then leave that
|
||||||
section as the currently active one so dataXX directives go into
|
section as the currently active one so dataXX directives go into
|
||||||
the language specific data area of the unwind info block. */
|
the language specific data area of the unwind info block. */
|
||||||
generate_unwind_image (text_name);
|
generate_unwind_image (now_seg);
|
||||||
demand_empty_rest_of_line ();
|
demand_empty_rest_of_line ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4057,7 +4128,6 @@ dot_endp (dummy)
|
|||||||
long where;
|
long where;
|
||||||
segT saved_seg;
|
segT saved_seg;
|
||||||
subsegT saved_subseg;
|
subsegT saved_subseg;
|
||||||
const char *sec_name, *text_name;
|
|
||||||
char *name, *p, c;
|
char *name, *p, c;
|
||||||
symbolS *sym;
|
symbolS *sym;
|
||||||
|
|
||||||
@ -4073,64 +4143,18 @@ dot_endp (dummy)
|
|||||||
saved_subseg = now_subseg;
|
saved_subseg = now_subseg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Use a slightly ugly scheme to derive the unwind section names from
|
|
||||||
the text section name:
|
|
||||||
|
|
||||||
text sect. unwind table sect.
|
|
||||||
name: name: comments:
|
|
||||||
---------- ----------------- --------------------------------
|
|
||||||
.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)
|
|
||||||
|
|
||||||
This mapping is done so that:
|
|
||||||
|
|
||||||
(a) An object file with unwind info only in .text will use
|
|
||||||
unwind section names .IA_64.unwind and .IA_64.unwind_info.
|
|
||||||
This follows the letter of the ABI and also ensures backwards
|
|
||||||
compatibility with older toolchains.
|
|
||||||
|
|
||||||
(b) An object file with unwind info in multiple text sections
|
|
||||||
will use separate unwind sections for each text section.
|
|
||||||
This allows us to properly set the "sh_info" and "sh_link"
|
|
||||||
fields in SHT_IA_64_UNWIND as required by the ABI and also
|
|
||||||
lets GNU ld support programs with multiple segments
|
|
||||||
containing unwind info (as might be the case for certain
|
|
||||||
embedded applications).
|
|
||||||
|
|
||||||
(c) An error is issued if there would be a name clash.
|
|
||||||
*/
|
|
||||||
text_name = segment_name (saved_seg);
|
|
||||||
if (strncmp (text_name, "_info", 5) == 0)
|
|
||||||
{
|
|
||||||
as_bad ("Illegal section name `%s' (causes unwind section name clash)",
|
|
||||||
text_name);
|
|
||||||
ignore_rest_of_line ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcmp (text_name, ".text") == 0)
|
|
||||||
text_name = "";
|
|
||||||
|
|
||||||
insn_group_break (1, 0, 0);
|
insn_group_break (1, 0, 0);
|
||||||
|
|
||||||
/* If there wasn't a .handlerdata, we haven't generated an image yet. */
|
/* If there wasn't a .handlerdata, we haven't generated an image yet. */
|
||||||
if (!unwind.info)
|
if (!unwind.info)
|
||||||
generate_unwind_image (text_name);
|
generate_unwind_image (saved_seg);
|
||||||
|
|
||||||
if (unwind.info || unwind.force_unwind_entry)
|
if (unwind.info || unwind.force_unwind_entry)
|
||||||
{
|
{
|
||||||
subseg_set (md.last_text_seg, 0);
|
subseg_set (md.last_text_seg, 0);
|
||||||
unwind.proc_end = expr_build_dot ();
|
unwind.proc_end = expr_build_dot ();
|
||||||
|
|
||||||
make_unw_section_name (SPECIAL_SECTION_UNWIND, text_name, sec_name);
|
start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
|
||||||
set_section ((char *) sec_name);
|
|
||||||
bfd_set_section_flags (stdoutput, now_seg,
|
|
||||||
SEC_LOAD | SEC_ALLOC | SEC_READONLY);
|
|
||||||
|
|
||||||
/* Make sure that section has 4 byte alignment for ILP32 and
|
/* Make sure that section has 4 byte alignment for ILP32 and
|
||||||
8 byte alignment for LP64. */
|
8 byte alignment for LP64. */
|
||||||
|
Loading…
Reference in New Issue
Block a user