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>
|
||||
|
||||
* config/obj-elf.c (obj_elf_change_section): Allow the
|
||||
|
@ -571,11 +571,6 @@ static char special_section_name[][20] =
|
||||
{".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
|
||||
instructions: */
|
||||
#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 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 void generate_unwind_image PARAMS ((const char *));
|
||||
static unsigned int get_saved_prologue_count PARAMS ((unsigned long));
|
||||
static void save_prologue_count PARAMS ((unsigned long, unsigned int));
|
||||
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
|
||||
unit (as opposed to the memory unit). */
|
||||
static int
|
||||
@ -3315,9 +3284,122 @@ dot_restorereg_p (dummy)
|
||||
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
|
||||
generate_unwind_image (text_name)
|
||||
const char *text_name;
|
||||
start_unwind_section (const segT text_seg, int sec_index)
|
||||
{
|
||||
/*
|
||||
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;
|
||||
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 (size != 0)
|
||||
{
|
||||
char *sec_name;
|
||||
expressionS exp;
|
||||
bfd_reloc_code_real_type reloc;
|
||||
|
||||
make_unw_section_name (SPECIAL_SECTION_UNWIND_INFO, text_name, sec_name);
|
||||
set_section (sec_name);
|
||||
bfd_set_section_flags (stdoutput, now_seg,
|
||||
SEC_LOAD | SEC_ALLOC | SEC_READONLY);
|
||||
start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
|
||||
|
||||
/* Make sure the section has 4 byte alignment for ILP32 and
|
||||
8 byte alignment for LP64. */
|
||||
@ -3406,13 +3484,6 @@ static void
|
||||
dot_handlerdata (dummy)
|
||||
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;
|
||||
|
||||
/* 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
|
||||
section as the currently active one so dataXX directives go into
|
||||
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 ();
|
||||
}
|
||||
|
||||
@ -4057,7 +4128,6 @@ dot_endp (dummy)
|
||||
long where;
|
||||
segT saved_seg;
|
||||
subsegT saved_subseg;
|
||||
const char *sec_name, *text_name;
|
||||
char *name, *p, c;
|
||||
symbolS *sym;
|
||||
|
||||
@ -4073,64 +4143,18 @@ dot_endp (dummy)
|
||||
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);
|
||||
|
||||
/* If there wasn't a .handlerdata, we haven't generated an image yet. */
|
||||
if (!unwind.info)
|
||||
generate_unwind_image (text_name);
|
||||
generate_unwind_image (saved_seg);
|
||||
|
||||
if (unwind.info || unwind.force_unwind_entry)
|
||||
{
|
||||
subseg_set (md.last_text_seg, 0);
|
||||
unwind.proc_end = expr_build_dot ();
|
||||
|
||||
make_unw_section_name (SPECIAL_SECTION_UNWIND, text_name, sec_name);
|
||||
set_section ((char *) sec_name);
|
||||
bfd_set_section_flags (stdoutput, now_seg,
|
||||
SEC_LOAD | SEC_ALLOC | SEC_READONLY);
|
||||
start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
|
||||
|
||||
/* Make sure that section has 4 byte alignment for ILP32 and
|
||||
8 byte alignment for LP64. */
|
||||
|
Loading…
Reference in New Issue
Block a user