summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schlemmer <azarah@gentoo.org>2003-06-28 12:37:27 +0000
committerMartin Schlemmer <azarah@gentoo.org>2003-06-28 12:37:27 +0000
commitae81827e1446e05b976c54119cd8c9687c5821a4 (patch)
tree909b77afd52c608e0f729d0829a3b27ebff1ecb5 /sys-devel/binutils/files/2.14
parentAdd patches from Redhat, as well as libtool fix. (diff)
downloadhistorical-ae81827e1446e05b976c54119cd8c9687c5821a4.tar.gz
historical-ae81827e1446e05b976c54119cd8c9687c5821a4.tar.bz2
historical-ae81827e1446e05b976c54119cd8c9687c5821a4.zip
Add patches from Redhat, as well as libtool fix.
Diffstat (limited to 'sys-devel/binutils/files/2.14')
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi.patch2690
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi2.patch651
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi3.patch509
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi4.patch384
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-eh-frame-ro.patch475
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-execstack.patch92
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-pred.patch46
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ltconfig-multilib.patch26
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie.patch632
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie2.patch25
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pni.patch442
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc-bigplt.patch16
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-ctors.patch20
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-prelink.patch132
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pt-gnu-stack.patch235
-rw-r--r--sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-sparc-nonpic.patch94
16 files changed, 6469 insertions, 0 deletions
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi.patch
new file mode 100644
index 000000000000..e8e6250c4ef2
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi.patch
@@ -0,0 +1,2690 @@
+2003-06-02 Alan Modra <amodra@bigpond.net.au>
+
+ * read.c (emit_expr): Set dot_value.
+ * dw2gencfi.c (output_fde): Remove pcrel reloc hack.
+
+2003-06-02 Alan Modra <amodra@bigpond.net.au>
+
+ * macro.c (sub_actual): Don't lose string if it turns out that
+ &string wasn't an arg.
+
+2003-05-31 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c (output_fde): Use fix_new to emit pc-relative reloc.
+ (cfi_finish): Set flag_traditional_format around .eh_frame data.
+
+2003-05-29 Richard Henderson <rth@redhat.com>
+
+ * config/tc-alpha.c (alpha_cur_ent_sym): Remove.
+ (all_frame_data, plast_frame_data, cur_frame_data): New.
+ (s_alpha_ent): Record data for dwarf2 cfi.
+ (s_alpha_end, s_alpha_mask, s_alpha_frame, s_alpha_prologue): Likewise.
+ (alpha_elf_md_end): Emit dwarf2 cfi for ecoff unwind directives.
+ * config/tc-alpha.h (md_end): New.
+ (DWARF2_DEFAULT_RETURN_COLUMN): New.
+ (DWARF2_CIE_DATA_ALIGNMENT): New.
+
+2003-05-27 Richard Henderson <rth@redhat.com>
+
+ * expr.c (make_expr_symbol): Fold FAKE_LABEL_NAME use into the
+ symbol_create call.
+ (current_location): Use symbol_temp_new_now.
+ * stabs.c (s_stab_generic): Use symbol_temp_new.
+ * symbols.c (temp_label_name): Remove.
+ (symbol_temp_new, symbol_temp_make): Use FAKE_LABEL_NAME.
+
+2003-05-27 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c, dw2gencfi.h: Rewrite from scratch.
+ * as.c (main): Always call cfi_finish.
+ * config/tc-i386.c (x86_dwarf2_return_column): New.
+ (x86_cie_data_alignment): New.
+ (md_begin): Set them.
+ (tc_x86_cfi_init): Remove.
+ (tc_x86_regname_to_dw2regnum): Fix 32-bit register numbers;
+ return int, not unsigned long; don't as_bad here.
+ (tc_x86_frame_initial_instructions): Streamline; use
+ updated api.
+ * config/tc-i386.h (tc_cfi_init): Remove.
+ (DWARF2_DEFAULT_RETURN_COLUMN): New.
+ (DWARF2_CIE_DATA_ALIGNMENT): New.
+
+2003-05-27 Richard Henderson <rth@redhat.com>
+
+ * symbols.c (temp_label_name): New.
+ (symbol_temp_new, symbol_temp_new_now, symbol_temp_make): New.
+ (symbol_set_value_now): New.
+ * symbols.h: Prototype them.
+ * dwarf2dbg.c: Use them.
+ (fake_label_name, symbol_new_now, set_symbol_value_now): Remove.
+
+testsuite/
+2003-05-31 Richard Henderson <rth@redhat.com>
+
+ * gas/alpha/elf-reloc-8.d: Correct .eh_frame relocs.
+ * gas/cfi/cfi-alpha-2.d: New.
+ * gas/cfi/cfi-alpha-2.s: New.
+ * gas/cfi/cfi.exp: Run it.
+
+2003-05-29 Richard Henderson <rth@redhat.com>
+
+ * gas/alpha/elf-reloc-8.d: Add .eh_frame relocs.
+ * gas/cfi/cfi-alpha-1.d: New.
+ * gas/cfi/cfi-alpha-1.s: New.
+ * gas/cfi/cfi.exp: Run it.
+
+2003-05-27 Richard Henderson <rth@redhat.com>
+
+ * gas/cfi/cfi-i386.d: Update for dw2gencfi rewrite.
+ * gas/cfi/cfi-x86_64.d: Likewise.
+ * gas/cfi/cfi-i386-2.d: New.
+ * gas/cfi/cfi-i386-2.s: New.
+
+--- gas/as.c 20 May 2003 14:31:44 -0000 1.44
++++ gas/as.c 27 May 2003 16:52:46 -0000 1.45
+@@ -911,9 +911,9 @@ main (argc, argv)
+ assembly debugging or on behalf of the compiler, emit it now. */
+ dwarf2_finish ();
+
+-#ifdef TARGET_USE_CFIPOP
++ /* If we constructed dwarf2 .eh_frame info, either via .cfi
++ directives from the user or by the backend, emit it now. */
+ cfi_finish ();
+-#endif
+
+ if (seen_at_least_1_file ()
+ && (flag_always_generate_output || had_errors () == 0))
+--- gas/dw2gencfi.c 21 May 2003 11:31:07 -0000 1.4
++++ gas/dw2gencfi.c 2 Jun 2003 22:48:59 -0000 1.7
+@@ -19,812 +19,789 @@
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+-#include <errno.h>
+ #include "as.h"
+ #include "dw2gencfi.h"
+
+-struct cie_entry
++
++/* We re-use DWARF2_LINE_MIN_INSN_LENGTH for the code alignment field
++ of the CIE. Default to 1 if not otherwise specified. */
++#ifndef DWARF2_LINE_MIN_INSN_LENGTH
++# define DWARF2_LINE_MIN_INSN_LENGTH 1
++#endif
++
++/* If TARGET_USE_CFIPOP is defined, it is required that the target
++ provide the following definitions. Otherwise provide them to
++ allow compilation to continue. */
++#ifndef TARGET_USE_CFIPOP
++# ifndef DWARF2_DEFAULT_RETURN_COLUMN
++# define DWARF2_DEFAULT_RETURN_COLUMN 0
++# endif
++# ifndef DWARF2_CIE_DATA_ALIGNMENT
++# define DWARF2_CIE_DATA_ALIGNMENT 1
++# endif
++#endif
++
++#ifndef tc_cfi_frame_initial_instructions
++# define tc_cfi_frame_initial_instructions() ((void)0)
++#endif
++
++
++struct cfi_insn_data
+ {
+- unsigned long offset;
+- size_t size;
+- void *data;
+- struct cie_entry *next;
++ struct cfi_insn_data *next;
++ int insn;
++ union {
++ struct {
++ unsigned reg;
++ offsetT offset;
++ } ri;
++
++ struct {
++ unsigned reg1;
++ unsigned reg2;
++ } rr;
++
++ unsigned r;
++ offsetT i;
++
++ struct {
++ symbolS *lab1;
++ symbolS *lab2;
++ } ll;
++ } u;
+ };
+
+-struct cfi_data
++struct fde_entry
+ {
+- enum cfi_insn insn;
+- long param[2];
+- struct cfi_data *next;
++ struct fde_entry *next;
++ symbolS *start_address;
++ symbolS *end_address;
++ struct cfi_insn_data *data;
++ struct cfi_insn_data **last;
++ unsigned int return_column;
+ };
+
+-struct cfi_info
++struct cie_entry
+ {
+- addressT start_address;
+- addressT end_address;
+- addressT last_address;
+- const char *labelname;
+- struct cfi_data *data;
+- struct cfi_info *next;
++ struct cie_entry *next;
++ symbolS *start_address;
++ unsigned int return_column;
++ struct cfi_insn_data *first, *last;
+ };
+
+-/* Current open CFI entry. */
+-static struct cfi_info *cfi_info;
++
++/* Current open FDE entry. */
++static struct fde_entry *cur_fde_data;
++static symbolS *last_address;
++static offsetT cur_cfa_offset;
++
++/* List of FDE entries. */
++static struct fde_entry *all_fde_data;
++static struct fde_entry **last_fde_data = &all_fde_data;
+
+ /* List of CIEs so that they could be reused. */
+ static struct cie_entry *cie_root;
+
+-/* Current target config. */
+-static struct cfi_config current_config;
++
++/* Construct a new FDE structure and add it to the end of the fde list. */
+
+-/* This is the main entry point to the CFI machinery. */
+-static void dot_cfi (int arg);
++static struct fde_entry *
++alloc_fde_entry (void)
++{
++ struct fde_entry *fde = xcalloc (1, sizeof (struct fde_entry));
+
+-const pseudo_typeS cfi_pseudo_table[] =
+- {
+- { "cfi_verbose", dot_cfi, CFI_verbose },
+- { "cfi_startproc", dot_cfi, CFI_startproc },
+- { "cfi_endproc", dot_cfi, CFI_endproc },
+- { "cfi_def_cfa", dot_cfi, CFA_def_cfa },
+- { "cfi_def_cfa_register", dot_cfi, CFA_def_cfa_register },
+- { "cfi_def_cfa_offset", dot_cfi, CFA_def_cfa_offset },
+- { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
+- { "cfi_offset", dot_cfi, CFA_offset },
+- { "cfi_register", dot_cfi, CFA_register },
+- { NULL, NULL, 0 }
+- };
++ cur_fde_data = fde;
++ *last_fde_data = fde;
++ last_fde_data = &fde->next;
++
++ fde->last = &fde->data;
++ fde->return_column = DWARF2_DEFAULT_RETURN_COLUMN;
++
++ return fde;
++}
++
++/* The following functions are available for a backend to construct its
++ own unwind information, usually from legacy unwind directives. */
++
++/* Construct a new INSN structure and add it to the end of the insn list
++ for the currently active FDE. */
+
+-static const char *
+-cfi_insn_str (enum cfi_insn insn)
++static struct cfi_insn_data *
++alloc_cfi_insn_data (void)
+ {
+- switch (insn)
+- {
+- case CFA_nop:
+- return "CFA_nop";
+- case CFA_set_loc:
+- return "CFA_set_loc";
+- case CFA_advance_loc1:
+- return "CFA_advance_loc1";
+- case CFA_advance_loc2:
+- return "CFA_advance_loc2";
+- case CFA_advance_loc4:
+- return "CFA_advance_loc4";
+- case CFA_offset_extended:
+- return "CFA_offset_extended";
+- case CFA_resotre_extended:
+- return "CFA_resotre_extended";
+- case CFA_undefined:
+- return "CFA_undefined";
+- case CFA_same_value:
+- return "CFA_same_value";
+- case CFA_register:
+- return "CFA_register";
+- case CFA_remember_state:
+- return "CFA_remember_state";
+- case CFA_restore_state:
+- return "CFA_restore_state";
+- case CFA_def_cfa:
+- return "CFA_def_cfa";
+- case CFA_def_cfa_register:
+- return "CFA_def_cfa_register";
+- case CFA_def_cfa_offset:
+- return "CFA_def_cfa_offset";
+- case CFA_advance_loc:
+- return "CFA_advance_loc";
+- case CFA_offset:
+- return "CFA_offset";
+- case CFA_restore:
+- return "CFA_restore";
+- default:
+- break;
+- }
++ struct cfi_insn_data *insn = xcalloc (1, sizeof (struct cfi_insn_data));
+
+- return "CFA_unknown";
++ *cur_fde_data->last = insn;
++ cur_fde_data->last = &insn->next;
++
++ return insn;
+ }
+
+-static struct cfi_data *
+-alloc_cfi_data (void)
++/* Construct a new FDE structure that begins at LABEL. */
++
++void
++cfi_new_fde (symbolS *label)
+ {
+- return (struct cfi_data *) xcalloc (sizeof (struct cfi_info), 1);
++ struct fde_entry *fde = alloc_fde_entry ();
++ fde->start_address = label;
++ last_address = label;
+ }
+
+-static struct cfi_info *
+-alloc_cfi_info (void)
++/* End the currently open FDE. */
++
++void
++cfi_end_fde (symbolS *label)
+ {
+- return (struct cfi_info *) xcalloc (sizeof (struct cfi_info), 1);
++ cur_fde_data->end_address = label;
++ cur_fde_data = NULL;
+ }
+
+-/* Parse arguments. */
+-static int
+-cfi_parse_arg (long *param, int resolvereg)
++/* Set the return column for the current FDE. */
++
++void
++cfi_set_return_column (unsigned regno)
+ {
+- long value;
+- int retval = -1;
+- int nchars;
++ cur_fde_data->return_column = regno;
++}
+
+- assert (param != NULL);
+- SKIP_WHITESPACE ();
++/* Add a CFI insn to advance the PC from the last address to LABEL. */
+
+- if (sscanf (input_line_pointer, "%li%n", &value, &nchars) >= 1)
+- {
+- input_line_pointer += nchars;
+- retval = 1;
+- }
+-#ifdef tc_regname_to_dw2regnum
+- else if (resolvereg && ((is_name_beginner (*input_line_pointer))
+- || (*input_line_pointer == '%'
+- && is_name_beginner (*(++input_line_pointer)))))
+- {
+- char *name, c, *p;
++void
++cfi_add_advance_loc (symbolS *label)
++{
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+
+- name = input_line_pointer;
+- c = get_symbol_end ();
+- p = input_line_pointer;
++ insn->insn = DW_CFA_advance_loc;
++ insn->u.ll.lab1 = last_address;
++ insn->u.ll.lab2 = label;
++
++ last_address = label;
++}
+
+- if ((value = tc_regname_to_dw2regnum (name)) >= 0)
+- retval = 1;
++/* Add a DW_CFA_offset record to the CFI data. */
+
+- *p = c;
+- }
+-#endif
+- else
+- as_bad (resolvereg ?
+- _("can't convert argument to a register number") :
+- _("can't convert argument to an integer"));
++void
++cfi_add_CFA_offset (unsigned regno, offsetT offset)
++{
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
++
++ insn->insn = DW_CFA_offset;
++ insn->u.ri.reg = regno;
++ insn->u.ri.offset = offset;
++}
+
+- if (retval > 0)
+- *param = value;
++/* Add a DW_CFA_def_cfa record to the CFI data. */
+
+- SKIP_WHITESPACE ();
+- if (*input_line_pointer == ',')
+- {
+- input_line_pointer++;
+- SKIP_WHITESPACE ();
+- }
++void
++cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
++{
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
++
++ insn->insn = DW_CFA_def_cfa;
++ insn->u.ri.reg = regno;
++ insn->u.ri.offset = offset;
+
+- return retval;
++ cur_cfa_offset = offset;
+ }
+
+-static int
+-cfi_parse_reg (long *param)
++/* Add a DW_CFA_register record to the CFI data. */
++
++void
++cfi_add_CFA_register (unsigned reg1, unsigned reg2)
+ {
+- return cfi_parse_arg (param, 1);
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
++
++ insn->insn = DW_CFA_register;
++ insn->u.rr.reg1 = reg1;
++ insn->u.rr.reg2 = reg2;
+ }
+
+-static int
+-cfi_parse_const (long *param)
++/* Add a DW_CFA_def_cfa_register record to the CFI data. */
++
++void
++cfi_add_CFA_def_cfa_register (unsigned regno)
+ {
+- return cfi_parse_arg (param, 0);
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
++
++ insn->insn = DW_CFA_def_cfa_register;
++ insn->u.r = regno;
+ }
+
++/* Add a DW_CFA_def_cfa_offset record to the CFI data. */
++
+ void
+-cfi_add_insn (enum cfi_insn insn, long param0, long param1)
++cfi_add_CFA_def_cfa_offset (offsetT offset)
+ {
+- struct cfi_data *data_ptr;
++ struct cfi_insn_data *insn = alloc_cfi_insn_data ();
++
++ insn->insn = DW_CFA_def_cfa_offset;
++ insn->u.i = offset;
+
+- if (!cfi_info->data)
+- {
+- cfi_info->data = alloc_cfi_data ();
+- data_ptr = cfi_info->data;
+- }
+- else
+- {
+- data_ptr = cfi_info->data;
++ cur_cfa_offset = offset;
++}
+
+- while (data_ptr && data_ptr->next)
+- data_ptr = data_ptr->next;
++
++/* Parse CFI assembler directives. */
+
+- data_ptr->next = alloc_cfi_data ();
++static void dot_cfi (int);
++static void dot_cfi_startproc (int);
++static void dot_cfi_endproc (int);
+
+- data_ptr = data_ptr->next;
+- }
++/* Fake CFI type; outside the byte range of any real CFI insn. */
++#define CFI_adjust_cfa_offset 0x100
+
+- data_ptr->insn = insn;
+- data_ptr->param[0] = param0;
+- data_ptr->param[1] = param1;
+-}
++const pseudo_typeS cfi_pseudo_table[] =
++ {
++ { "cfi_startproc", dot_cfi_startproc, 0 },
++ { "cfi_endproc", dot_cfi_endproc, 0 },
++ { "cfi_def_cfa", dot_cfi, DW_CFA_def_cfa },
++ { "cfi_def_cfa_register", dot_cfi, DW_CFA_def_cfa_register },
++ { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
++ { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
++ { "cfi_offset", dot_cfi, DW_CFA_offset },
++ { "cfi_register", dot_cfi, DW_CFA_register },
++ { NULL, NULL, 0 }
++ };
+
+ static void
+-cfi_advance_loc (void)
++cfi_parse_separator (void)
+ {
+- addressT curr_address = frag_now_fix ();
+- if (cfi_info->last_address == curr_address)
+- return;
+- cfi_add_insn (CFA_advance_loc,
+- (long) (curr_address - cfi_info->last_address), 0);
+- cfi_info->last_address = curr_address;
++ SKIP_WHITESPACE ();
++ if (*input_line_pointer == ',')
++ input_line_pointer++;
++ else
++ as_bad (_("missing separator"));
+ }
+
+-static long
+-get_current_offset (struct cfi_info *info)
++static unsigned
++cfi_parse_reg (void)
+ {
+- long current_offset = 0;
+- struct cfi_data *data = info->data;
++ int regno;
++ expressionS exp;
++
++#ifdef tc_regname_to_dw2regnum
++ SKIP_WHITESPACE ();
++ if (is_name_beginner (*input_line_pointer)
++ || (*input_line_pointer == '%'
++ && is_name_beginner (*++input_line_pointer)))
++ {
++ char *name, c;
++
++ name = input_line_pointer;
++ c = get_symbol_end ();
++
++ if ((regno = tc_regname_to_dw2regnum (name)) < 0)
++ {
++ as_bad (_("bad register expression"));
++ regno = 0;
++ }
++
++ *input_line_pointer = c;
++ return regno;
++ }
++#endif
+
+- current_offset = 0;
+- while (data)
++ expression (&exp);
++ switch (exp.X_op)
+ {
+- if (data->insn == CFA_def_cfa)
+- current_offset = data->param[1];
+- else if (data->insn == CFA_def_cfa_offset)
+- current_offset = data->param[0];
+- data = data->next;
++ case O_register:
++ case O_constant:
++ regno = exp.X_add_number;
++ break;
++
++ default:
++ as_bad (_("bad register expression"));
++ regno = 0;
++ break;
+ }
+
+- return current_offset;
++ return regno;
++}
++
++static offsetT
++cfi_parse_const (void)
++{
++ return get_absolute_expression ();
+ }
+
+ static void
+-cfi_make_insn (int arg)
++dot_cfi (int arg)
+ {
+- long param[2] = { 0, 0 };
++ offsetT offset;
++ unsigned reg1, reg2;
+
+- if (!cfi_info)
++ if (!cur_fde_data)
+ {
+ as_bad (_("CFI instruction used without previous .cfi_startproc"));
+ return;
+ }
+
+- cfi_advance_loc ();
++ /* If the last address was not at the current PC, advance to current. */
++ if (symbol_get_frag (last_address) != frag_now
++ || S_GET_VALUE (last_address) != frag_now_fix ())
++ cfi_add_advance_loc (symbol_temp_new_now ());
+
+ switch (arg)
+ {
+ /* Instructions that take two arguments (register, integer). */
+- case CFA_offset:
+- case CFA_def_cfa:
+- if (cfi_parse_reg (&param[0]) < 0)
+- {
+- as_bad (_("first argument to %s is not a register"),
+- cfi_insn_str (arg));
+- return;
+- }
+- if (cfi_parse_const (&param[1]) < 0)
+- {
+- as_bad (_("second argument to %s is not a number"),
+- cfi_insn_str (arg));
+- return;
+- }
++ case DW_CFA_offset:
++ case DW_CFA_def_cfa:
++ reg1 = cfi_parse_reg ();
++ cfi_parse_separator ();
++ offset = cfi_parse_const ();
++
++ if (arg == DW_CFA_def_cfa)
++ cfi_add_CFA_def_cfa (reg1, offset);
++ else
++ cfi_add_CFA_offset (reg1, offset);
+ break;
+
+- case CFA_register:
+- if (cfi_parse_reg (&param[0]) < 0)
+- {
+- as_bad (_("first argument to %s is not a register"),
+- cfi_insn_str (arg));
+- return;
+- }
+- if (cfi_parse_reg (&param[1]) < 0)
+- {
+- as_bad (_("second argument to %s is not a register"),
+- cfi_insn_str (arg));
+- return;
+- }
++ /* Instructions that take two arguments (register, register). */
++ case DW_CFA_register:
++ reg1 = cfi_parse_reg ();
++ cfi_parse_separator ();
++ reg2 = cfi_parse_reg ();
++
++ cfi_add_CFA_register (reg1, reg2);
+ break;
+
+ /* Instructions that take one register argument. */
+- case CFA_def_cfa_register:
+- if (cfi_parse_reg (&param[0]) < 0)
+- {
+- as_bad (_("argument to %s is not a register"), cfi_insn_str (arg));
+- return;
+- }
++ case DW_CFA_def_cfa_register:
++ reg1 = cfi_parse_reg ();
++ cfi_add_CFA_def_cfa_register (reg1);
+ break;
+
+ /* Instructions that take one integer argument. */
+- case CFA_def_cfa_offset:
+- if (cfi_parse_const (&param[0]) < 0)
+- {
+- as_bad (_("argument to %s is not a number"), cfi_insn_str (arg));
+- return;
+- }
++ case DW_CFA_def_cfa_offset:
++ offset = cfi_parse_const ();
++ cfi_add_CFA_def_cfa_offset (offset);
+ break;
+
+ /* Special handling for pseudo-instruction. */
+ case CFI_adjust_cfa_offset:
+- if (cfi_parse_const (&param[0]) < 0)
+- {
+- as_bad (_("argument to %s is not a number"),
+- ".cfi_adjust_cfa_offset");
+- return;
+- }
+- param[0] += get_current_offset (cfi_info);
+- arg = CFA_def_cfa_offset;
++ offset = cfi_parse_const ();
++ cfi_add_CFA_def_cfa_offset (cur_cfa_offset + offset);
+ break;
+
+ default:
+- as_bad (_("unknown CFI instruction %d (%s)"), arg, cfi_insn_str (arg));
+- return;
++ abort ();
+ }
+- cfi_add_insn (arg, param[0], param[1]);
++
++ demand_empty_rest_of_line ();
+ }
+
+-static symbolS *
+-cfi_get_label (void)
++static void
++dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
+ {
+- char symname[40], *symbase=".Llbl_cfi";
+- symbolS *symbolP;
+- unsigned int i = 0;
++ int simple = 0;
+
+- snprintf (symname, sizeof (symname), "%s_0x%lx",
+- symbase, (long) frag_now_fix ());
+- while ((symbolP = symbol_find (symname)))
++ if (cur_fde_data)
++ {
++ as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
++ return;
++ }
++
++ cfi_new_fde (symbol_temp_new_now ());
++
++ SKIP_WHITESPACE ();
++ if (is_name_beginner (*input_line_pointer))
+ {
+- if ((S_GET_VALUE (symbolP) == frag_now_fix ())
+- && (S_GET_SEGMENT (symbolP) == now_seg))
+- return symbolP;
++ char *name, c;
+
+- snprintf (symname, sizeof (symname), "%s_0x%lx_%u",
+- symbase, (long) frag_now_fix (), i++);
++ name = input_line_pointer;
++ c = get_symbol_end ();
++
++ if (strcmp (name, "simple") == 0)
++ {
++ simple = 1;
++ *input_line_pointer = c;
++ }
++ else
++ input_line_pointer = name;
+ }
+-#ifdef BFD_ASSEMBLER
+- symbolP = (symbolS *) local_symbol_make (symname, now_seg,
+- (valueT) frag_now_fix (),
+- frag_now);
+-#else
+- symbolP = symbol_make (symname);
+-#endif
+- return symbolP;
++ demand_empty_rest_of_line ();
++
++ if (!simple)
++ tc_cfi_frame_initial_instructions ();
+ }
+
+ static void
+-dot_cfi_startproc (void)
++dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED)
+ {
+-#ifdef tc_cfi_frame_initial_instructions
+- const char *simple = "simple";
+-#endif
+-
+- if (cfi_info)
++ if (! cur_fde_data)
+ {
+- as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
++ as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
+ return;
+ }
+
+-#if defined(TARGET_USE_CFIPOP)
+- /* Because this file is linked even for architectures that
+- don't use CFI, we must wrap this call. */
+- if (current_config.addr_length == 0)
+- tc_cfi_init ();
+-#endif
+-
+- cfi_info = alloc_cfi_info ();
++ cfi_end_fde (symbol_temp_new_now ());
++}
+
+- cfi_info->start_address = frag_now_fix ();
+- cfi_info->last_address = cfi_info->start_address;
+- cfi_info->labelname = S_GET_NAME (cfi_get_label ());
++
++/* Emit a single byte into the current segment. */
+
+- SKIP_WHITESPACE ();
+-#ifdef tc_cfi_frame_initial_instructions
+- if (strncmp (simple, input_line_pointer, strlen (simple)) != 0)
+- tc_cfi_frame_initial_instructions ();
+- else
+- input_line_pointer += strlen (simple);
+-#endif
++static inline void
++out_one (int byte)
++{
++ FRAG_APPEND_1_CHAR (byte);
+ }
+
+-#define cfi_is_advance_insn(insn) \
+- ((insn >= CFA_set_loc && insn <= CFA_advance_loc4) \
+- || insn == CFA_advance_loc)
++/* Emit a two-byte word into the current segment. */
+
+-/* Output CFI instructions to the file. */
++static inline void
++out_two (int data)
++{
++ md_number_to_chars (frag_more (2), data, 2);
++}
+
+-enum data_types
+- {
+- t_ascii = 0,
+- t_byte = 1,
+- t_half = 2,
+- t_long = 4,
+- t_quad = 8,
+- t_uleb128 = 0x10,
+- t_sleb128 = 0x11
+- };
++/* Emit a four byte word into the current segment. */
+
+-static int
+-output_data (char **p, unsigned long *size, enum data_types type, long value)
++static inline void
++out_four (int data)
+ {
+- char *ptr = *p;
+- unsigned int ret_size;
+-
+- switch (type)
+- {
+- case t_byte:
+- ret_size = 1;
+- break;
+- case t_half:
+- ret_size = 2;
+- break;
+- case t_long:
+- ret_size = 4;
+- break;
+- case t_quad:
+- case t_uleb128:
+- case t_sleb128:
+- ret_size = 8;
+- break;
+- default:
+- /* This should never happen - throw an internal error. */
+- as_fatal (_("unknown type %d"), type);
+- return 0;
+- }
+-
+- if (*size < ret_size)
+- {
+- as_bad (_("output_data buffer is too small"));
+- return 0;
+- }
+-
+- switch (type)
+- {
+- case t_byte:
+- *ptr = (char) value;
+- if (verbose)
+- printf ("\t.byte\t0x%x\n", (unsigned char) *ptr);
+- break;
+- case t_half:
+- *(short *) ptr = (short) value & 0xFFFF;
+- if (verbose)
+- printf ("\t.half\t0x%x\n", (unsigned short) *ptr);
+- break;
+- case t_long:
+- *(int *) ptr = (int) value & 0xFFFFFFFF;
+- if (verbose)
+- printf ("\t.long\t0x%x\n", (unsigned int) *ptr);
+- break;
+- case t_quad:
+- *(long long *) ptr = (long long) value & 0xFFFFFFFF;
+- if (verbose)
+- printf ("\t.quad\t0x%x\n", (unsigned int) *ptr);
+- break;
+- case t_uleb128:
+- case t_sleb128:
+- ret_size = output_leb128 (ptr, value, type == t_sleb128);
+- if (verbose)
+- printf ("\t.%s\t0x%lx\n",
+- type == t_sleb128 ? "sleb128" : "uleb128",
+- value);
+- break;
+- default:
+- as_fatal (_("unknown type %d"), type);
+- return 0;
+- }
++ md_number_to_chars (frag_more (4), data, 4);
++}
+
+- *size -= ret_size;
+- *p += ret_size;
++/* Emit an unsigned "little-endian base 128" number. */
+
+- return ret_size;
++static void
++out_uleb128 (addressT value)
++{
++ output_leb128 (frag_more (sizeof_leb128 (value, 0)), value, 0);
+ }
+
+-static int
+-cfi_output_insn (struct cfi_data *data, char **buf, unsigned long *buf_size)
++/* Emit an unsigned "little-endian base 128" number. */
++
++static void
++out_sleb128 (offsetT value)
+ {
+- char **pbuf = buf, *orig_buf = *buf;
+- unsigned long size;
++ output_leb128 (frag_more (sizeof_leb128 (value, 1)), value, 1);
++}
+
+- if (!data || !buf)
+- as_fatal (_("cfi_output_insn called with NULL pointer"));
++static void
++output_cfi_insn (struct cfi_insn_data *insn)
++{
++ offsetT offset;
++ unsigned int regno;
+
+- switch (data->insn)
++ switch (insn->insn)
+ {
+- case CFA_advance_loc:
+- if (verbose)
+- printf ("\t# %s(%ld)\n", cfi_insn_str (data->insn),
+- data->param[0]);
+- if (data->param[0] <= 0x3F)
+- {
+- output_data (pbuf, buf_size, t_byte, CFA_advance_loc +
+- (data->param[0] / current_config.code_align));
++ case DW_CFA_advance_loc:
++ {
++ symbolS *from = insn->u.ll.lab1;
++ symbolS *to = insn->u.ll.lab2;
++
++ if (symbol_get_frag (to) == symbol_get_frag (from))
++ {
++ addressT delta = S_GET_VALUE (to) - S_GET_VALUE (from);
++ addressT scaled = delta / DWARF2_LINE_MIN_INSN_LENGTH;
++
++ if (scaled <= 0x3F)
++ out_one (DW_CFA_advance_loc + scaled);
++ else if (delta <= 0xFF)
++ {
++ out_one (DW_CFA_advance_loc1);
++ out_one (delta);
++ }
++ else if (delta <= 0xFFFF)
++ {
++ out_one (DW_CFA_advance_loc2);
++ out_two (delta);
++ }
++ else
++ {
++ out_one (DW_CFA_advance_loc4);
++ out_four (delta);
++ }
++ }
++ else
++ {
++ expressionS exp;
++
++ exp.X_op = O_subtract;
++ exp.X_add_symbol = to;
++ exp.X_op_symbol = from;
++ exp.X_add_number = 0;
++
++ /* The code in ehopt.c expects that one byte of the encoding
++ is already allocated to the frag. This comes from the way
++ that it scans the .eh_frame section looking first for the
++ .byte DW_CFA_advance_loc4. */
++ frag_more (1);
++
++ frag_var (rs_cfa, 4, 0, DWARF2_LINE_MIN_INSN_LENGTH << 3,
++ make_expr_symbol (&exp), frag_now_fix () - 1,
++ (char *) frag_now);
++ }
++ }
++ break;
++
++ case DW_CFA_def_cfa:
++ offset = insn->u.ri.offset;
++ if (offset < 0)
++ {
++ out_one (DW_CFA_def_cfa_sf);
++ out_uleb128 (insn->u.ri.reg);
++ out_uleb128 (offset);
+ }
+- else if (data->param[0] <= 0xFF)
++ else
+ {
+- output_data (pbuf, buf_size, t_byte, CFA_advance_loc1);
+- output_data (pbuf, buf_size, t_byte,
+- data->param[0] / current_config.code_align);
++ out_one (DW_CFA_def_cfa);
++ out_uleb128 (insn->u.ri.reg);
++ out_uleb128 (offset);
+ }
+- else if (data->param[0] <= 0xFFFF)
++ break;
++
++ case DW_CFA_def_cfa_register:
++ out_one (DW_CFA_def_cfa_register);
++ out_uleb128 (insn->u.i);
++ break;
++
++ case DW_CFA_def_cfa_offset:
++ offset = insn->u.i;
++ if (offset < 0)
+ {
+- output_data (pbuf, buf_size, t_byte, CFA_advance_loc2);
+- output_data (pbuf, buf_size, t_half,
+- data->param[0] / current_config.code_align);
++ out_one (DW_CFA_def_cfa_offset_sf);
++ out_sleb128 (offset);
+ }
+ else
+ {
+- output_data (pbuf, buf_size, t_byte, CFA_advance_loc4);
+- output_data (pbuf, buf_size, t_long,
+- data->param[0] / current_config.code_align);
++ out_one (DW_CFA_def_cfa_offset);
++ out_uleb128 (offset);
+ }
+ break;
+
+- case CFA_def_cfa:
+- if (verbose)
+- printf ("\t# CFA_def_cfa(%ld,%ld)\n",
+- data->param[0], data->param[1]);
+- output_data (pbuf, buf_size, t_byte, CFA_def_cfa);
+- output_data (pbuf, buf_size, t_uleb128, data->param[0]);
+- output_data (pbuf, buf_size, t_uleb128, data->param[1]);
+- break;
+-
+- case CFA_def_cfa_register:
+- case CFA_def_cfa_offset:
+- if (verbose)
+- printf ("\t# %s(%ld)\n", cfi_insn_str (data->insn),
+- data->param[0]);
+- output_data (pbuf, buf_size, t_byte, data->insn);
+- output_data (pbuf, buf_size, t_uleb128, data->param[0]);
+- break;
+-
+- case CFA_offset:
+- if (verbose)
+- printf ("\t# %s(%ld,%ld)\n", cfi_insn_str (data->insn),
+- data->param[0], data->param[1]);
+-
+- /* Check whether to use CFA_offset or CFA_offset_extended. */
+- if (data->param[0] <= 0x3F)
+- output_data (pbuf, buf_size, t_byte, CFA_offset + data->param[0]);
++ case DW_CFA_offset:
++ regno = insn->u.ri.reg;
++ offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
++ if (offset < 0)
++ {
++ out_one (DW_CFA_offset_extended);
++ out_uleb128 (regno);
++ out_sleb128 (offset);
++ }
++ else if (regno <= 0x3F)
++ {
++ out_one (DW_CFA_offset + regno);
++ out_uleb128 (offset);
++ }
+ else
+ {
+- output_data (pbuf, buf_size, t_byte, CFA_offset_extended);
+- output_data (pbuf, buf_size, t_uleb128, data->param[0]);
++ out_one (DW_CFA_offset_extended);
++ out_uleb128 (regno);
++ out_uleb128 (offset);
+ }
+- output_data (pbuf, buf_size, t_uleb128,
+- data->param[1] / current_config.data_align);
+ break;
+
+- case CFA_register:
+- if (verbose)
+- printf ("\t# %s(%ld,%ld)\n", cfi_insn_str (data->insn),
+- data->param[0], data->param[1]);
+- output_data (pbuf, buf_size, t_byte, CFA_register);
+- output_data (pbuf, buf_size, t_uleb128, data->param[0]);
+- output_data (pbuf, buf_size, t_uleb128, data->param[1]);
+- break;
+-
+- case CFA_nop:
+- if (verbose)
+- printf ("\t# CFA_nop\n");
+- output_data (pbuf, buf_size, t_byte, CFA_nop);
++ case DW_CFA_register:
++ out_one (DW_CFA_register);
++ out_uleb128 (insn->u.rr.reg1);
++ out_uleb128 (insn->u.rr.reg2);
++ break;
++
++ case DW_CFA_nop:
++ out_one (DW_CFA_nop);
+ break;
+
+ default:
+- as_warn ("CFA_unknown[%d](%ld,%ld)", data->insn,
+- data->param[0], data->param[1]);
++ abort ();
+ }
+- size = *pbuf - orig_buf;
+- *buf = *pbuf;
+- *buf_size -= size;
+- return size;
+ }
+
+ static void
+-dot_cfi_endproc (void)
++output_cie (struct cie_entry *cie)
+ {
+- struct cfi_data *data_ptr;
+- struct cie_entry *cie_ptr;
+- char *cie_buf, *fde_buf, *pbuf, *where;
+- unsigned long buf_size, cie_size, fde_size, last_cie_offset;
+- unsigned long fde_initloc_offset, fde_len_offset, fde_offset;
+- segT saved_seg, cfi_seg;
++ symbolS *after_size_address, *end_address;
+ expressionS exp;
++ struct cfi_insn_data *i;
+
+- if (! cfi_info)
+- {
+- as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
+- return;
+- }
+- cfi_info->end_address = frag_now_fix ();
+-
+- /* Open .eh_frame section. */
+- saved_seg = now_seg;
+- cfi_seg = subseg_new (".eh_frame", 0);
+-#ifdef BFD_ASSEMBLER
+- bfd_set_section_flags (stdoutput, cfi_seg,
+- SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+-#endif
+- subseg_set (cfi_seg, 0);
++ cie->start_address = symbol_temp_new_now ();
++ after_size_address = symbol_temp_make ();
++ end_address = symbol_temp_make ();
++
++ exp.X_op = O_subtract;
++ exp.X_add_symbol = end_address;
++ exp.X_op_symbol = after_size_address;
++ exp.X_add_number = 0;
++
++ emit_expr (&exp, 4); /* Length */
++ symbol_set_value_now (after_size_address);
++ out_four (0); /* CIE id */
++ out_one (DW_CIE_VERSION); /* Version */
++ out_one ('z'); /* Augmentation */
++ out_one ('R');
++ out_one (0);
++ out_uleb128 (DWARF2_LINE_MIN_INSN_LENGTH); /* Code alignment */
++ out_sleb128 (DWARF2_CIE_DATA_ALIGNMENT); /* Data alignment */
++ out_one (cie->return_column); /* Return column */
++ out_uleb128 (1); /* Augmentation size */
++ out_one (DW_EH_PE_pcrel | DW_EH_PE_sdata4);
++
++ if (cie->first)
++ for (i = cie->first; i != cie->last; i = i->next)
++ output_cfi_insn (i);
+
+- /* Build CIE. */
+- cie_buf = xcalloc (1024, 1);
+- /* Skip space for CIE length. */
+- pbuf = cie_buf + 4;
+- buf_size = 1020;
+-
+- if (verbose)
+- printf ("# CIE *****\n");
+-
+- /* CIE id. */
+- output_data (&pbuf, &buf_size, t_long, 0x0);
+- /* Version. */
+- output_data (&pbuf, &buf_size, t_byte, 1);
+- /* Augmentation. */
+- output_data (&pbuf, &buf_size, t_byte, 0);
+- /* Code alignment. */
+- output_data (&pbuf, &buf_size, t_uleb128, current_config.code_align);
+- /* Data alignment. */
+- output_data (&pbuf, &buf_size, t_sleb128, current_config.data_align);
+- /* Return address column. */
+- output_data (&pbuf, &buf_size, t_byte, current_config.ra_column);
+-
+- /* Build CFI instructions. */
+- data_ptr = cfi_info->data;
+- while (data_ptr && !cfi_is_advance_insn (data_ptr->insn))
+- {
+- cfi_output_insn (data_ptr, &pbuf, &buf_size);
+- data_ptr = data_ptr->next;
+- }
+-
+- /* Align the whole data to current_config.eh_align. */
+- cie_size = pbuf - cie_buf;
+- cie_size += current_config.eh_align - cie_size % current_config.eh_align;
+-
+- /* CIE length. */
+- pbuf = cie_buf;
+- output_data (&pbuf, &buf_size, t_long, cie_size - 4);
+-
+- /* OK, we built the CIE. Let's write it to the file... */
+- last_cie_offset = frag_now_fix ();
+-
+- /* Check if we have already emitted the exactly same CIE.
+- If yes then use its offset instead and don't put out
+- the new one. */
+- cie_ptr = cie_root;
+- while (cie_ptr)
+- {
+- if (cie_ptr->size == cie_size - 4
+- && memcmp (cie_ptr->data, cie_buf + 4, cie_ptr->size) == 0)
+- break;
+- cie_ptr = cie_ptr->next;
+- }
+-
+- /* If we have found the same CIE, use it... */
+- if (cie_ptr)
+- {
+- if (verbose)
+- printf ("# Duplicate CIE found. Previous is at offset %lu\n",
+- cie_ptr->offset);
+- last_cie_offset = cie_ptr->offset;
+- }
+- else
+- {
+- /* Otherwise join this CIE to the list. */
+- where = (unsigned char *) frag_more (cie_size);
+- memcpy (where, cie_buf, cie_size);
+- if (cie_root)
+- {
+- cie_ptr = cie_root;
+- while (cie_ptr->next)
+- cie_ptr = cie_ptr->next;
+- cie_ptr->next = calloc (sizeof (struct cie_entry), 1);
+- cie_ptr = cie_ptr->next;
+- }
+- else
+- {
+- cie_root = calloc (sizeof (struct cie_entry), 1);
+- cie_ptr = cie_root;
+- }
++ frag_align (2, 0, 0);
++ symbol_set_value_now (end_address);
++}
+
+- cie_ptr->size = cie_size - 4;
+- cie_ptr->data = calloc (cie_ptr->size, 1);
+- cie_ptr->offset = last_cie_offset;
+- memcpy (cie_ptr->data, cie_buf + 4, cie_ptr->size);
+- }
++static void
++output_fde (struct fde_entry *fde, struct cie_entry *cie,
++ struct cfi_insn_data *first)
++{
++ symbolS *after_size_address, *end_address;
++ expressionS exp;
+
+- /* Clean up. */
+- free (cie_buf);
++ after_size_address = symbol_temp_make ();
++ end_address = symbol_temp_make ();
+
+- /* Build the FDE... */
+- fde_buf = xcalloc (1024, 1);
+- pbuf = fde_buf;
+- buf_size = 1024;
++ exp.X_op = O_subtract;
++ exp.X_add_symbol = end_address;
++ exp.X_op_symbol = after_size_address;
++ exp.X_add_number = 0;
++ emit_expr (&exp, 4); /* Length */
++ symbol_set_value_now (after_size_address);
+
+- /* Offset of this FDE in current fragment. */
+- fde_offset = frag_now_fix ();
++ exp.X_add_symbol = after_size_address;
++ exp.X_op_symbol = cie->start_address;
++ emit_expr (&exp, 4); /* CIE offset */
++
++ exp.X_add_symbol = fde->start_address;
++ exp.X_op_symbol = symbol_temp_new_now ();
++ emit_expr (&exp, 4); /* Code offset */
+
+- if (verbose)
+- {
+- printf ("# FDE: start=0x%lx, end=0x%lx, delta=%d\n",
+- (long) cfi_info->start_address,
+- (long) cfi_info->end_address,
+- (int) (cfi_info->end_address - cfi_info->start_address));
+- }
++ exp.X_add_symbol = fde->end_address;
++ exp.X_op_symbol = fde->start_address; /* Code length */
++ emit_expr (&exp, 4);
+
+- /* FDE length (t_long, 4 bytes) - will be set later. */
+- fde_len_offset = pbuf - fde_buf;
+- pbuf += 4;
+- buf_size -= 4;
++ out_uleb128 (0); /* Augmentation size */
+
+- /* CIE pointer - offset from here. */
+- output_data (&pbuf, &buf_size, t_long, fde_offset - last_cie_offset + 4);
++ for (; first; first = first->next)
++ output_cfi_insn (first);
+
+- /* FDE initial location - this must be set relocatable! */
+- fde_initloc_offset = pbuf - fde_buf + fde_offset;
+- output_data (&pbuf, &buf_size, current_config.addr_length,
+- cfi_info->start_address);
++ frag_align (2, 0, 0);
++ symbol_set_value_now (end_address);
++}
+
+- /* FDE address range. */
+- output_data (&pbuf, &buf_size, current_config.addr_length,
+- cfi_info->end_address - cfi_info->start_address);
++static struct cie_entry *
++select_cie_for_fde (struct fde_entry *fde, struct cfi_insn_data **pfirst)
++{
++ struct cfi_insn_data *i, *j;
++ struct cie_entry *cie;
+
+- while (data_ptr)
++ for (cie = cie_root; cie; cie = cie->next)
+ {
+- cfi_output_insn (data_ptr, &pbuf, &buf_size);
+- data_ptr = data_ptr->next;
+- }
++ if (cie->return_column != fde->return_column)
++ continue;
++ for (i = cie->first, j = fde->data;
++ i != cie->last && j != NULL;
++ i = i->next, j = j->next)
++ {
++ if (i->insn != j->insn)
++ goto fail;
++ switch (i->insn)
++ {
++ case DW_CFA_advance_loc:
++ /* We reached the first advance in the FDE, but did not
++ reach the end of the CIE list. */
++ goto fail;
+
+- fde_size = pbuf - fde_buf;
+- fde_size += current_config.eh_align - fde_size % current_config.eh_align;
++ case DW_CFA_offset:
++ case DW_CFA_def_cfa:
++ if (i->u.ri.reg != j->u.ri.reg)
++ goto fail;
++ if (i->u.ri.offset != j->u.ri.offset)
++ goto fail;
++ break;
+
+- /* Now we can set FDE length. */
+- pbuf = fde_buf + fde_len_offset;
+- buf_size = 4;
+- output_data (&pbuf, &buf_size, t_long, fde_size - 4);
++ case DW_CFA_register:
++ if (i->u.rr.reg1 != j->u.rr.reg1)
++ goto fail;
++ if (i->u.rr.reg2 != j->u.rr.reg2)
++ goto fail;
++ break;
+
+- /* Copy FDE to objfile. */
+- where = (unsigned char *) frag_more (fde_size);
+- memcpy (where, fde_buf, fde_size);
++ case DW_CFA_def_cfa_register:
++ if (i->u.r != j->u.r)
++ goto fail;
++ break;
+
+- /* Set relocation for initial address. */
+- buf_size = current_config.addr_length;
+- memset (&exp, 0, sizeof (exp));
+- exp.X_op = O_symbol;
+- exp.X_add_symbol = symbol_find (cfi_info->labelname);
+- fix_new_exp (frag_now, fde_initloc_offset,
+- current_config.addr_length,
+- &exp, 0, current_config.reloc_type);
++ case DW_CFA_def_cfa_offset:
++ if (i->u.i != j->u.i)
++ goto fail;
++ break;
+
+- /* Clean up. */
+- free (fde_buf);
++ default:
++ abort ();
++ }
++ }
+
+- free (cfi_info);
+- cfi_info = NULL;
++ /* Success if we reached the end of the CIE list, and we've either
++ run out of FDE entries or we've encountered an advance. */
++ if (i == cie->last && (!j || j->insn == DW_CFA_advance_loc))
++ {
++ *pfirst = j;
++ return cie;
++ }
+
+- /* Restore previous segment. */
+- subseg_set (saved_seg, 0);
+-}
++ fail:;
++ }
+
+-void
+-dot_cfi (int arg)
+-{
+- long param;
++ cie = xmalloc (sizeof (struct cie_entry));
++ cie->next = cie_root;
++ cie_root = cie;
++ cie->return_column = fde->return_column;
++ cie->first = fde->data;
+
+- switch (arg)
+- {
+- case CFI_startproc:
+- dot_cfi_startproc ();
+- break;
+- case CFI_endproc:
+- dot_cfi_endproc ();
+- break;
+- case CFA_def_cfa:
+- case CFA_def_cfa_register:
+- case CFA_def_cfa_offset:
+- case CFA_offset:
+- case CFA_register:
+- case CFI_adjust_cfa_offset:
+- cfi_make_insn (arg);
+- break;
+- case CFI_verbose:
+- if (cfi_parse_const (&param) >= 0)
+- verbose = (int) param;
+- else
+- verbose = 1;
+- break;
+- default:
+- as_bad (_("unknown CFI code 0x%x (%s)"), arg, cfi_insn_str (arg));
++ for (i = cie->first; i ; i = i->next)
++ if (i->insn == DW_CFA_advance_loc)
+ break;
+- }
+- ignore_rest_of_line ();
+-}
+
+-void
+-cfi_set_config (struct cfi_config *cfg)
+-{
+- assert (cfg != NULL);
+- assert (cfg->addr_length > 0);
++ cie->last = i;
++ *pfirst = i;
++
++ output_cie (cie);
+
+- current_config = *cfg;
++ return cie;
+ }
+
+ void
+ cfi_finish (void)
+ {
+- if (cfi_info)
+- as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
++ segT cfi_seg;
++ struct fde_entry *fde;
++ int save_flag_traditional_format;
++
++ if (cur_fde_data)
++ {
++ as_bad (_("open CFI at the end of file; missing .cfi_endproc directive"));
++ cur_fde_data->end_address = cur_fde_data->start_address;
++ }
++
++ if (all_fde_data == 0)
++ return;
++
++ /* Open .eh_frame section. */
++ cfi_seg = subseg_new (".eh_frame", 0);
++#ifdef BFD_ASSEMBLER
++ bfd_set_section_flags (stdoutput, cfi_seg,
++ SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
++#endif
++ subseg_set (cfi_seg, 0);
++ record_alignment (cfi_seg, 2);
++
++ /* Make sure check_eh_frame doesn't do anything with our output. */
++ save_flag_traditional_format = flag_traditional_format;
++ flag_traditional_format = 1;
++
++ for (fde = all_fde_data; fde ; fde = fde->next)
++ {
++ struct cfi_insn_data *first;
++ struct cie_entry *cie;
++
++ cie = select_cie_for_fde (fde, &first);
++ output_fde (fde, cie, first);
++ }
++
++ flag_traditional_format = save_flag_traditional_format;
+ }
+--- gas/dw2gencfi.h 20 May 2003 07:58:06 -0000 1.1
++++ gas/dw2gencfi.h 27 May 2003 16:52:46 -0000 1.2
+@@ -24,77 +24,23 @@
+
+ #include "elf/dwarf2.h"
+
+-struct cfi_config {
+- /* Target address length in bytes. (usually 4 or 8).
+- Round it up for archs like S/390 with 31b addresses. */
+- unsigned int addr_length;
+-
+- /* Alignment of .eh_frame blocks in bytes (usually 1, 4 or 8). */
+- unsigned int eh_align;
+-
+- /* Code alignment (1 for x86/amd64 machines, 4 or 8 for
+- RISC machines). Consult Dwarf2 standard for details. */
+- int code_align;
+-
+- /* Data (stack) alignment (-4 on x86, -8 on amd64, something
+- positive on archs where stack grows up). Consult Dwarf2
+- standard for details. */
+- int data_align;
+-
+- /* Return address column (0x8 on x86, 0x10 on amd64). Consult
+- Dwarf2 standard for details. */
+- int ra_column;
+-
+- /* Relocation type for init_addr FDE record. (BFD_RELOC_64
+- on amd64). */
+- int reloc_type;
+-};
+-
+-/* Codes of CFI instructions taken from Dwarf2 standard. */
+-enum cfi_insn {
+- CFA_nop = DW_CFA_nop,
+- CFA_set_loc = DW_CFA_set_loc,
+- CFA_advance_loc1 = DW_CFA_advance_loc1,
+- CFA_advance_loc2 = DW_CFA_advance_loc2,
+- CFA_advance_loc4 = DW_CFA_advance_loc4,
+- CFA_offset_extended = DW_CFA_offset_extended,
+- CFA_resotre_extended = DW_CFA_restore_extended,
+- CFA_undefined = DW_CFA_undefined,
+- CFA_same_value = DW_CFA_same_value,
+- CFA_register = DW_CFA_register,
+- CFA_remember_state = DW_CFA_remember_state,
+- CFA_restore_state = DW_CFA_restore_state,
+- CFA_def_cfa = DW_CFA_def_cfa,
+- CFA_def_cfa_register = DW_CFA_def_cfa_register,
+- CFA_def_cfa_offset = DW_CFA_def_cfa_offset,
+- CFA_advance_loc = DW_CFA_advance_loc,
+- CFA_offset = DW_CFA_offset,
+- CFA_restore = DW_CFA_restore,
+-
+- /* These don't belong to the standard. */
+- CFI_startproc = 0xff00,
+- CFI_endproc = 0xff01,
+- CFI_adjust_cfa_offset = 0xff10,
+- CFI_verbose = 0xffff
+-};
++struct symbol;
+
+ extern const pseudo_typeS cfi_pseudo_table[];
+
+-/* Insert .cfi_* directives to the list of pseudo-ops. */
+-void cfi_pop_insert PARAMS ((void));
+-
+-/* Set/change setup of the CFI machinery. This change won't
+- affect already generated CIEs/FDEs. */
+-void cfi_set_config PARAMS ((struct cfi_config *cfg));
+-
+ /* cfi_finish() is called at the end of file. It will complain if
+ the last CFI wasn't properly closed by .cfi_endproc. */
+-void cfi_finish PARAMS ((void));
++extern void cfi_finish (void);
+
+-/* Add CFI instruction to the list of instructions
+- of the current frame. cfi_add_insn() could be used
+- in tc_cfi_frame_initial_instructions() to add instructions
+- needed for every frame (ie. those that usually go to CIE). */
+-void cfi_add_insn (enum cfi_insn insn, long param0, long param1);
++/* Entry points for backends to add unwind information. */
++extern void cfi_new_fde (struct symbol *);
++extern void cfi_end_fde (struct symbol *);
++extern void cfi_set_return_column (unsigned);
++extern void cfi_add_advance_loc (struct symbol *);
++extern void cfi_add_CFA_offset (unsigned, offsetT);
++extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
++extern void cfi_add_CFA_register (unsigned, unsigned);
++extern void cfi_add_CFA_def_cfa_register (unsigned);
++extern void cfi_add_CFA_def_cfa_offset (offsetT);
+
+ #endif /* DW2GENCFI_H */
+--- gas/dwarf2dbg.c 21 Apr 2003 18:23:25 -0000 1.62
++++ gas/dwarf2dbg.c 27 May 2003 16:00:04 -0000 1.63
+@@ -157,9 +157,6 @@ static bfd_boolean loc_directive_seen;
+ /* Current location as indicated by the most recent .loc directive. */
+ static struct dwarf2_line_info current;
+
+-/* Fake label name. */
+-static char const fake_label_name[] = ".L0\001";
+-
+ /* The size of an address on the target. */
+ static unsigned int sizeof_address;
+
+@@ -174,8 +171,6 @@ static void out_two PARAMS ((int));
+ static void out_four PARAMS ((int));
+ static void out_abbrev PARAMS ((int, int));
+ static void out_uleb128 PARAMS ((addressT));
+-static symbolS *symbol_new_now PARAMS ((void));
+-static void set_symbol_value_now PARAMS ((symbolS *));
+ static offsetT get_frag_fix PARAMS ((fragS *));
+ static void out_set_addr PARAMS ((segT, fragS *, addressT));
+ static int size_inc_line_addr PARAMS ((int, addressT));
+@@ -621,25 +616,6 @@ out_abbrev (name, form)
+ out_uleb128 (form);
+ }
+
+-/* Create a new fake symbol whose value is the current position. */
+-
+-static symbolS *
+-symbol_new_now ()
+-{
+- return symbol_new (fake_label_name, now_seg, frag_now_fix (), frag_now);
+-}
+-
+-/* Set the value of SYM to the current position in the current segment. */
+-
+-static void
+-set_symbol_value_now (sym)
+- symbolS *sym;
+-{
+- S_SET_SEGMENT (sym, now_seg);
+- S_SET_VALUE (sym, frag_now_fix ());
+- symbol_set_frag (sym, frag_now);
+-}
+-
+ /* Get the size of a fragment. */
+
+ static offsetT
+@@ -676,7 +652,7 @@ out_set_addr (seg, frag, ofs)
+ expressionS expr;
+ symbolS *sym;
+
+- sym = symbol_new (fake_label_name, seg, ofs, frag);
++ sym = symbol_temp_new (seg, ofs, frag);
+
+ out_opcode (DW_LNS_extended_op);
+ out_uleb128 (sizeof_address + 1);
+@@ -894,8 +870,8 @@ relax_inc_line_addr (line_delta, seg, to
+ expressionS expr;
+ int max_chars;
+
+- to_sym = symbol_new (fake_label_name, seg, to_ofs, to_frag);
+- from_sym = symbol_new (fake_label_name, seg, from_ofs, from_frag);
++ to_sym = symbol_temp_new (seg, to_ofs, to_frag);
++ from_sym = symbol_temp_new (seg, from_ofs, from_frag);
+
+ expr.X_op = O_subtract;
+ expr.X_add_symbol = to_sym;
+@@ -1124,9 +1100,9 @@ out_debug_line (line_seg)
+
+ subseg_set (line_seg, 0);
+
+- line_start = symbol_new_now ();
+- prologue_end = symbol_make (fake_label_name);
+- line_end = symbol_make (fake_label_name);
++ line_start = symbol_temp_new_now ();
++ prologue_end = symbol_temp_make ();
++ line_end = symbol_temp_make ();
+
+ /* Total length of the information for this compilation unit. */
+ expr.X_op = O_subtract;
+@@ -1188,13 +1164,13 @@ out_debug_line (line_seg)
+
+ out_file_list ();
+
+- set_symbol_value_now (prologue_end);
++ symbol_set_value_now (prologue_end);
+
+ /* For each section, emit a statement program. */
+ for (s = all_segs; s; s = s->next)
+ process_entries (s->seg, s->head->head);
+
+- set_symbol_value_now (line_end);
++ symbol_set_value_now (line_end);
+ }
+
+ /* Emit data for .debug_aranges. */
+@@ -1250,11 +1226,11 @@ out_debug_aranges (aranges_seg, info_seg
+ symbolS *beg, *end;
+
+ frag = first_frag_for_seg (s->seg);
+- beg = symbol_new (fake_label_name, s->seg, 0, frag);
++ beg = symbol_temp_new (s->seg, 0, frag);
+ s->text_start = beg;
+
+ frag = last_frag_for_seg (s->seg);
+- end = symbol_new (fake_label_name, s->seg, get_frag_fix (frag), frag);
++ end = symbol_temp_new (s->seg, get_frag_fix (frag), frag);
+ s->text_end = end;
+
+ expr.X_op = O_symbol;
+@@ -1322,8 +1298,8 @@ out_debug_info (info_seg, abbrev_seg, li
+
+ subseg_set (info_seg, 0);
+
+- info_start = symbol_new_now ();
+- info_end = symbol_make (fake_label_name);
++ info_start = symbol_temp_new_now ();
++ info_end = symbol_temp_make ();
+
+ /* Compilation Unit length. */
+ expr.X_op = O_subtract;
+@@ -1421,7 +1397,7 @@ out_debug_info (info_seg, abbrev_seg, li
+ dwarf2 draft has no standard code for assembler. */
+ out_two (DW_LANG_Mips_Assembler);
+
+- set_symbol_value_now (info_end);
++ symbol_set_value_now (info_end);
+ }
+
+ void
+--- gas/expr.c 18 Oct 2002 01:56:39 -0000 1.46
++++ gas/expr.c 27 May 2003 19:19:29 -0000 1.47
+@@ -67,7 +67,6 @@ make_expr_symbol (expressionP)
+ expressionS *expressionP;
+ {
+ expressionS zero;
+- const char *fake;
+ symbolS *symbolP;
+ struct expr_symbol_line *n;
+
+@@ -91,13 +90,11 @@ make_expr_symbol (expressionP)
+ expressionP = &zero;
+ }
+
+- fake = FAKE_LABEL_NAME;
+-
+ /* Putting constant symbols in absolute_section rather than
+ expr_section is convenient for the old a.out code, for which
+ S_GET_SEGMENT does not always retrieve the value put in by
+ S_SET_SEGMENT. */
+- symbolP = symbol_create (fake,
++ symbolP = symbol_create (FAKE_LABEL_NAME,
+ (expressionP->X_op == O_constant
+ ? absolute_section
+ : expr_section),
+@@ -745,13 +742,8 @@ current_location (expressionp)
+ }
+ else
+ {
+- symbolS *symbolp;
+-
+- symbolp = symbol_new (FAKE_LABEL_NAME, now_seg,
+- (valueT) frag_now_fix (),
+- frag_now);
+ expressionp->X_op = O_symbol;
+- expressionp->X_add_symbol = symbolp;
++ expressionp->X_add_symbol = symbol_temp_new_now ();
+ expressionp->X_add_number = 0;
+ }
+ }
+--- gas/macro.c 13 Mar 2003 11:49:33 -0000 1.21
++++ gas/macro.c 2 Jun 2003 15:03:20 -0000 1.22
+@@ -637,6 +637,7 @@ sub_actual (start, in, t, formal_hash, k
+ {
+ /* Doing this permits people to use & in macro bodies. */
+ sb_add_char (out, '&');
++ sb_add_sb (out, t);
+ }
+ else if (copyifnotthere)
+ {
+--- gas/read.c 20 May 2003 07:58:06 -0000 1.62
++++ gas/read.c 2 Jun 2003 22:48:58 -0000 1.63
+@@ -3444,6 +3444,8 @@ emit_expr (exp, nbytes)
+ if (need_pass_2)
+ return;
+
++ dot_value = frag_now_fix ();
++
+ #ifndef NO_LISTING
+ #ifdef OBJ_ELF
+ /* When gcc emits DWARF 1 debugging pseudo-ops, a line number will
+--- gas/stabs.c 18 May 2002 12:53:30 -0000 1.19
++++ gas/stabs.c 27 May 2003 19:19:29 -0000 1.20
+@@ -371,13 +371,11 @@ s_stab_generic (what, stab_secname, stab
+ }
+ else
+ {
+- const char *fake;
+ symbolS *symbol;
+ expressionS exp;
+
+ /* Arrange for a value representing the current location. */
+- fake = FAKE_LABEL_NAME;
+- symbol = symbol_new (fake, saved_seg, dot, saved_frag);
++ symbol = symbol_temp_new (saved_seg, dot, saved_frag);
+
+ exp.X_op = O_symbol;
+ exp.X_add_symbol = symbol;
+--- gas/symbols.c 20 May 2003 07:58:06 -0000 1.44
++++ gas/symbols.c 27 May 2003 19:19:29 -0000 1.46
+@@ -588,6 +588,27 @@ symbol_make (name)
+ return (symbolP);
+ }
+
++symbolS *
++symbol_temp_new (seg, ofs, frag)
++ segT seg;
++ valueT ofs;
++ fragS *frag;
++{
++ return symbol_new (FAKE_LABEL_NAME, seg, ofs, frag);
++}
++
++symbolS *
++symbol_temp_new_now ()
++{
++ return symbol_temp_new (now_seg, frag_now_fix (), frag_now);
++}
++
++symbolS *
++symbol_temp_make ()
++{
++ return symbol_make (FAKE_LABEL_NAME);
++}
++
+ /* Implement symbol table lookup.
+ In: A symbol's name as a string: '\0' can't be part of a symbol name.
+ Out: NULL if the name was not in the symbol table, else the address
+@@ -2059,6 +2080,17 @@ symbol_set_value_expression (s, exp)
+ if (LOCAL_SYMBOL_CHECK (s))
+ s = local_symbol_convert ((struct local_symbol *) s);
+ s->sy_value = *exp;
++}
++
++/* Set the value of SYM to the current position in the current segment. */
++
++void
++symbol_set_value_now (sym)
++ symbolS *sym;
++{
++ S_SET_SEGMENT (sym, now_seg);
++ S_SET_VALUE (sym, frag_now_fix ());
++ symbol_set_frag (sym, frag_now);
+ }
+
+ /* Set the frag of a symbol. */
+--- gas/symbols.h 20 May 2003 07:58:06 -0000 1.12
++++ gas/symbols.h 27 May 2003 16:00:04 -0000 1.13
+@@ -59,6 +59,10 @@ symbolS *symbol_create PARAMS ((const ch
+ fragS * frag));
+ struct local_symbol *local_symbol_make PARAMS ((const char *name, segT section,
+ valueT value, fragS * frag));
++symbolS *symbol_temp_new PARAMS ((segT, valueT, fragS *));
++symbolS *symbol_temp_new_now PARAMS ((void));
++symbolS *symbol_temp_make PARAMS ((void));
++
+ symbolS *colon PARAMS ((const char *sym_name));
+ void local_colon PARAMS ((int n));
+ void symbol_begin PARAMS ((void));
+@@ -172,6 +176,7 @@ extern symbolS *symbol_next PARAMS ((sym
+ extern expressionS *symbol_get_value_expression PARAMS ((symbolS *));
+ extern void symbol_set_value_expression PARAMS ((symbolS *,
+ const expressionS *));
++extern void symbol_set_value_now PARAMS ((symbolS *));
+ extern void symbol_set_frag PARAMS ((symbolS *, fragS *));
+ extern fragS *symbol_get_frag PARAMS ((symbolS *));
+ extern void symbol_mark_used PARAMS ((symbolS *));
+--- gas/config/tc-alpha.c 3 May 2003 16:04:11 -0000 1.56
++++ gas/config/tc-alpha.c 30 May 2003 03:01:11 -0000 1.57
+@@ -60,6 +60,7 @@
+ #ifdef OBJ_ELF
+ #include "elf/alpha.h"
+ #include "dwarf2dbg.h"
++#include "dw2gencfi.h"
+ #endif
+
+ #include "safe-ctype.h"
+@@ -407,11 +408,6 @@ static symbolS *alpha_lit8_symbol;
+ static offsetT alpha_lit8_literal;
+ #endif
+
+-#ifdef OBJ_ELF
+-/* The active .ent symbol. */
+-static symbolS *alpha_cur_ent_sym;
+-#endif
+-
+ /* Is the assembler not allowed to use $at? */
+ static int alpha_noat_on = 0;
+
+@@ -4382,6 +4378,25 @@ s_alpha_sdata (ignore)
+ #endif
+
+ #ifdef OBJ_ELF
++struct alpha_elf_frame_data
++{
++ symbolS *func_sym;
++ symbolS *func_end_sym;
++ symbolS *prologue_sym;
++ unsigned int mask;
++ unsigned int fmask;
++ int fp_regno;
++ int ra_regno;
++ offsetT frame_size;
++ offsetT mask_offset;
++ offsetT fmask_offset;
++
++ struct alpha_elf_frame_data *next;
++};
++
++static struct alpha_elf_frame_data *all_frame_data;
++static struct alpha_elf_frame_data **plast_frame_data = &all_frame_data;
++static struct alpha_elf_frame_data *cur_frame_data;
+
+ /* Handle the .section pseudo-op. This is like the usual one, but it
+ clears alpha_insn_label and restores auto alignment. */
+@@ -4418,12 +4433,21 @@ s_alpha_ent (dummy)
+ {
+ symbolS *sym;
+
+- if (alpha_cur_ent_sym)
++ if (cur_frame_data)
+ as_warn (_("nested .ent directives"));
+
+ sym = symbol_find_or_make (name);
+ symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
+- alpha_cur_ent_sym = sym;
++
++ cur_frame_data = calloc (1, sizeof (*cur_frame_data));
++ cur_frame_data->func_sym = sym;
++
++ /* Provide sensible defaults. */
++ cur_frame_data->fp_regno = 30; /* sp */
++ cur_frame_data->ra_regno = 26; /* ra */
++
++ *plast_frame_data = cur_frame_data;
++ plast_frame_data = &cur_frame_data->next;
+
+ /* The .ent directive is sometimes followed by a number. Not sure
+ what it really means, but ignore it. */
+@@ -4463,22 +4487,27 @@ s_alpha_end (dummy)
+ symbolS *sym;
+
+ sym = symbol_find (name);
+- if (sym != alpha_cur_ent_sym)
++ if (!cur_frame_data)
++ as_warn (_(".end directive without matching .ent"));
++ else if (sym != cur_frame_data->func_sym)
+ as_warn (_(".end directive names different symbol than .ent"));
+
+ /* Create an expression to calculate the size of the function. */
+ if (sym)
+ {
+- symbol_get_obj (sym)->size =
+- (expressionS *) xmalloc (sizeof (expressionS));
+- symbol_get_obj (sym)->size->X_op = O_subtract;
+- symbol_get_obj (sym)->size->X_add_symbol
+- = symbol_new ("L0\001", now_seg, frag_now_fix (), frag_now);
+- symbol_get_obj (sym)->size->X_op_symbol = sym;
+- symbol_get_obj (sym)->size->X_add_number = 0;
++ OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym);
++ expressionS *exp = xmalloc (sizeof (expressionS));
++
++ obj->size = exp;
++ exp->X_op = O_subtract;
++ exp->X_add_symbol = symbol_temp_new_now ();
++ exp->X_op_symbol = sym;
++ exp->X_add_number = 0;
++
++ cur_frame_data->func_end_sym = exp->X_add_symbol;
+ }
+
+- alpha_cur_ent_sym = NULL;
++ cur_frame_data = NULL;
+
+ *input_line_pointer = name_end;
+ }
+@@ -4498,7 +4527,45 @@ s_alpha_mask (fp)
+ ecoff_directive_mask (0);
+ }
+ else
+- discard_rest_of_line ();
++ {
++ long val;
++ offsetT offset;
++
++ if (!cur_frame_data)
++ {
++ if (fp)
++ as_warn (_(".fmask outside of .ent"));
++ else
++ as_warn (_(".mask outside of .ent"));
++ discard_rest_of_line ();
++ return;
++ }
++
++ if (get_absolute_expression_and_terminator (&val) != ',')
++ {
++ if (fp)
++ as_warn (_("bad .fmask directive"));
++ else
++ as_warn (_("bad .mask directive"));
++ --input_line_pointer;
++ discard_rest_of_line ();
++ return;
++ }
++
++ offset = get_absolute_expression ();
++ demand_empty_rest_of_line ();
++
++ if (fp)
++ {
++ cur_frame_data->fmask = val;
++ cur_frame_data->fmask_offset = offset;
++ }
++ else
++ {
++ cur_frame_data->mask = val;
++ cur_frame_data->mask_offset = offset;
++ }
++ }
+ }
+
+ static void
+@@ -4508,7 +4575,36 @@ s_alpha_frame (dummy)
+ if (ECOFF_DEBUGGING)
+ ecoff_directive_frame (0);
+ else
+- discard_rest_of_line ();
++ {
++ long val;
++
++ if (!cur_frame_data)
++ {
++ as_warn (_(".frame outside of .ent"));
++ discard_rest_of_line ();
++ return;
++ }
++
++ cur_frame_data->fp_regno = tc_get_register (1);
++
++ SKIP_WHITESPACE ();
++ if (*input_line_pointer++ != ','
++ || get_absolute_expression_and_terminator (&val) != ',')
++ {
++ as_warn (_("bad .frame directive"));
++ --input_line_pointer;
++ discard_rest_of_line ();
++ return;
++ }
++ cur_frame_data->frame_size = val;
++
++ cur_frame_data->ra_regno = tc_get_register (0);
++
++ /* Next comes the "offset of saved $a0 from $sp". In gcc terms
++ this is current_function_pretend_args_size. There's no place
++ to put this value, so ignore it. */
++ s_ignore (42);
++ }
+ }
+
+ static void
+@@ -4524,7 +4620,7 @@ s_alpha_prologue (ignore)
+ if (ECOFF_DEBUGGING)
+ sym = ecoff_get_cur_proc_sym ();
+ else
+- sym = alpha_cur_ent_sym;
++ sym = cur_frame_data ? cur_frame_data->func_sym : NULL;
+
+ if (sym == NULL)
+ {
+@@ -4549,6 +4645,9 @@ s_alpha_prologue (ignore)
+ as_bad (_("Invalid argument %d to .prologue."), arg);
+ break;
+ }
++
++ if (cur_frame_data)
++ cur_frame_data->prologue_sym = symbol_temp_new_now ();
+ }
+
+ static char *first_file_directive;
+@@ -4641,6 +4740,87 @@ s_alpha_coff_wrapper (which)
+ as_bad (_("ECOFF debugging is disabled."));
+ ignore_rest_of_line ();
+ }
++}
++
++/* Called at the end of assembly. Here we emit unwind info for frames
++ unless the compiler has done it for us. */
++
++void
++alpha_elf_md_end (void)
++{
++ struct alpha_elf_frame_data *p;
++
++ if (cur_frame_data)
++ as_warn (_(".ent directive without matching .end"));
++
++ /* If someone has generated the unwind info themselves, great. */
++ if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL)
++ return;
++
++ /* Generate .eh_frame data for the unwind directives specified. */
++ for (p = all_frame_data; p ; p = p->next)
++ if (p->prologue_sym)
++ {
++ /* Create a temporary symbol at the same location as our
++ function symbol. This prevents problems with globals. */
++ cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym),
++ S_GET_VALUE (p->func_sym),
++ symbol_get_frag (p->func_sym)));
++
++ cfi_set_return_column (p->ra_regno);
++ cfi_add_CFA_def_cfa_register (30);
++ if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size)
++ {
++ unsigned int mask;
++ offsetT offset;
++
++ cfi_add_advance_loc (p->prologue_sym);
++
++ if (p->fp_regno != 30)
++ if (p->frame_size != 0)
++ cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size);
++ else
++ cfi_add_CFA_def_cfa_register (p->fp_regno);
++ else if (p->frame_size != 0)
++ cfi_add_CFA_def_cfa_offset (p->frame_size);
++
++ mask = p->mask;
++ offset = p->mask_offset;
++
++ /* Recall that $26 is special-cased and stored first. */
++ if ((mask >> 26) & 1)
++ {
++ cfi_add_CFA_offset (26, offset);
++ offset += 8;
++ mask &= ~(1 << 26);
++ }
++ while (mask)
++ {
++ unsigned int i;
++ i = mask & -mask;
++ mask ^= i;
++ i = ffs (i) - 1;
++
++ cfi_add_CFA_offset (i, offset);
++ offset += 8;
++ }
++
++ mask = p->fmask;
++ offset = p->fmask_offset;
++ while (mask)
++ {
++ unsigned int i;
++ i = mask & -mask;
++ mask ^= i;
++ i = ffs (i) - 1;
++
++ cfi_add_CFA_offset (i + 32, offset);
++ offset += 8;
++ }
++ }
++
++ cfi_end_fde (p->func_end_sym);
++ }
+ }
+ #endif /* OBJ_ELF */
+
+--- gas/config/tc-alpha.h 7 Nov 2002 00:42:18 -0000 1.16
++++ gas/config/tc-alpha.h 30 May 2003 03:01:11 -0000 1.17
+@@ -128,6 +128,11 @@ extern flagword alpha_elf_section_flags
+ #define tc_frob_file_before_fix() alpha_before_fix ()
+ extern void alpha_before_fix PARAMS ((void));
+
++#ifdef OBJ_ELF
++#define md_end alpha_elf_md_end
++extern void alpha_elf_md_end PARAMS ((void));
++#endif
++
+ /* New fields for supporting explicit relocations (such as !literal to mark
+ where a pointer is loaded from the global table, and !lituse_base to track
+ all of the normal uses of that pointer). */
+@@ -156,4 +161,6 @@ do { \
+ (long) FIX->tc_fix_data.next_reloc); \
+ } while (0)
+
+-#define DWARF2_LINE_MIN_INSN_LENGTH 4
++#define DWARF2_LINE_MIN_INSN_LENGTH 4
++#define DWARF2_DEFAULT_RETURN_COLUMN 26
++#define DWARF2_CIE_DATA_ALIGNMENT -8
+--- gas/config/tc-i386.c 20 May 2003 07:58:06 -0000 1.139
++++ gas/config/tc-i386.c 27 May 2003 16:52:47 -0000 1.140
+@@ -319,6 +319,12 @@ static unsigned int no_cond_jump_promoti
+ /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */
+ symbolS *GOT_symbol;
+
++/* The dwarf2 return column, adjusted for 32 or 64 bit. */
++unsigned int x86_dwarf2_return_column;
++
++/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */
++int x86_cie_data_alignment;
++
+ /* Interface to relax_segment.
+ There are 3 major relax states for 386 jump insns because the
+ different types of jumps add different sizes to frags when we're
+@@ -987,6 +993,17 @@ md_begin ()
+ record_alignment (bss_section, 2);
+ }
+ #endif
++
++ if (flag_code == CODE_64BIT)
++ {
++ x86_dwarf2_return_column = 16;
++ x86_cie_data_alignment = -8;
++ }
++ else
++ {
++ x86_dwarf2_return_column = 8;
++ x86_cie_data_alignment = -4;
++ }
+ }
+
+ void
+@@ -6301,42 +6318,15 @@ intel_putback_token ()
+ prev_token.str = NULL;
+ }
+
+-void
+-tc_x86_cfi_init (void)
+-{
+- struct cfi_config cfi_config;
+-
+- if (flag_code == CODE_64BIT)
+- {
+- cfi_config.addr_length = 8;
+- cfi_config.eh_align = 8;
+- cfi_config.code_align = 1;
+- cfi_config.data_align = -8;
+- cfi_config.ra_column = 0x10;
+- cfi_config.reloc_type = BFD_RELOC_64;
+- }
+- else
+- {
+- cfi_config.addr_length = 4;
+- cfi_config.eh_align = 4;
+- cfi_config.code_align = 1;
+- cfi_config.data_align = -4;
+- cfi_config.ra_column = 0x08;
+- cfi_config.reloc_type = BFD_RELOC_32;
+- }
+-
+- cfi_set_config (&cfi_config);
+-}
+-
+-unsigned long
++int
+ tc_x86_regname_to_dw2regnum (const char *regname)
+ {
+ unsigned int regnum;
+ unsigned int regnames_count;
+ char *regnames_32[] =
+ {
+- "eax", "ebx", "ecx", "edx",
+- "edi", "esi", "ebp", "esp",
++ "eax", "ecx", "edx", "ebx",
++ "esp", "ebp", "esi", "edi",
+ "eip"
+ };
+ char *regnames_64[] =
+@@ -6364,21 +6354,18 @@ tc_x86_regname_to_dw2regnum (const char
+ if (strcmp (regname, regnames[regnum]) == 0)
+ return regnum;
+
+- as_bad (_("unknown register name '%s'"), regname);
+ return -1;
+ }
+
+ void
+ tc_x86_frame_initial_instructions (void)
+ {
+- if (flag_code == CODE_64BIT)
+- {
+- cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("rsp"), 8);
+- cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("rip"), -8);
+- }
+- else
+- {
+- cfi_add_insn (CFA_def_cfa, tc_x86_regname_to_dw2regnum ("esp"), 4);
+- cfi_add_insn (CFA_offset, tc_x86_regname_to_dw2regnum ("eip"), -4);
+- }
++ static unsigned int sp_regno;
++
++ if (!sp_regno)
++ sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
++ ? "rsp" : "esp");
++
++ cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
++ cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
+ }
+--- gas/config/tc-i386.h 20 May 2003 07:58:07 -0000 1.40
++++ gas/config/tc-i386.h 27 May 2003 16:52:47 -0000 1.41
+@@ -546,18 +546,18 @@ extern void sco_id PARAMS ((void));
+ #endif
+
+ /* We want .cfi_* pseudo-ops for generating unwind info. */
+-#define TARGET_USE_CFIPOP
+-#ifdef TARGET_USE_CFIPOP
++#define TARGET_USE_CFIPOP 1
+
+-#define tc_cfi_init() tc_x86_cfi_init ()
+-extern void tc_x86_cfi_init PARAMS ((void));
++extern unsigned int x86_dwarf2_return_column;
++#define DWARF2_DEFAULT_RETURN_COLUMN x86_dwarf2_return_column
++
++extern int x86_cie_data_alignment;
++#define DWARF2_CIE_DATA_ALIGNMENT x86_cie_data_alignment
+
+ #define tc_regname_to_dw2regnum tc_x86_regname_to_dw2regnum
+-extern unsigned long tc_x86_regname_to_dw2regnum PARAMS ((const char *regname));
++extern int tc_x86_regname_to_dw2regnum PARAMS ((const char *regname));
+
+ #define tc_cfi_frame_initial_instructions tc_x86_frame_initial_instructions
+ extern void tc_x86_frame_initial_instructions PARAMS ((void));
+-
+-#endif /* TARGET_USE_CFIPOP */
+
+ #endif /* TC_I386 */
+--- gas/testsuite/gas/alpha/elf-reloc-8.d 7 Nov 2002 00:42:19 -0000 1.1
++++ gas/testsuite/gas/alpha/elf-reloc-8.d 31 May 2003 19:36:45 -0000 1.3
+@@ -307,3 +307,24 @@ OFFSET *TYPE *VALUE
+ 0*0000048 REFQUAD \.init\.text\+0x0*00005f0
+ 0*0000050 REFQUAD \.init\.data\+0x0*0000029
+ 0*0000058 REFQUAD \.init\.text\+0x0*0000610
++
++
++RELOCATION RECORDS FOR \[\.eh_frame\]:
++OFFSET *TYPE *VALUE
++0*000001c SREL32 \.init\.text
++0*0000034 SREL32 \.init\.text\+0x0*0000050
++0*0000048 SREL32 \.init\.text\+0x0*0000080
++0*000005c SREL32 \.init\.text\+0x0*00000b0
++0*0000080 SREL32 \.init\.text\+0x0*00002c0
++0*00000a0 SREL32 \.init\.text\+0x0*00005a0
++0*00000b8 SREL32 \.init\.text\+0x0*00005f0
++0*00000cc SREL32 \.init\.text\+0x0*0000610
++0*00000e0 SREL32 \.init\.text\+0x0*0000630
++0*00000fc SREL32 \.init\.text\+0x0*0000750
++0*0000120 SREL32 \.init\.text\+0x0*0000990
++0*000013c SREL32 \.init\.text\+0x0*0000a10
++0*0000150 SREL32 \.init\.text\+0x0*0000a20
++0*0000164 SREL32 \.init\.text\+0x0*0000a40
++0*000017c SREL32 \.init\.text\+0x0*0000a90
++0*0000190 SREL32 \.init\.text\+0x0*0000aa0
++0*00001a4 SREL32 \.text
+--- gas/testsuite/gas/cfi/cfi-i386.d 20 May 2003 14:31:44 -0000 1.2
++++ gas/testsuite/gas/cfi/cfi-i386.d 27 May 2003 16:52:49 -0000 1.3
+@@ -2,50 +2,46 @@
+ #name: CFI on i386
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 00000014 00000000 CIE
+ Version: 1
+- Augmentation: ""
++ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -4
+ Return address column: 8
++ Augmentation data: 1b
+
+- DW_CFA_def_cfa: r7 ofs 4
++ DW_CFA_def_cfa: r4 ofs 4
+ DW_CFA_offset: r8 at cfa-4
+ DW_CFA_nop
+ DW_CFA_nop
+
+-00000014 00000014 00000018 FDE cie=00000000 pc=00000000..00000012
+- DW_CFA_advance_loc: 6 to 00000006
++00000018 00000014 0000001c FDE cie=00000000 pc=00000020..00000032
++ DW_CFA_advance_loc: 6 to 00000026
+ DW_CFA_def_cfa_offset: 4664
+- DW_CFA_advance_loc: 11 to 00000011
++ DW_CFA_advance_loc: 11 to 00000031
+ DW_CFA_def_cfa_offset: 4
+- DW_CFA_nop
+
+-0000002c 00000018 00000030 FDE cie=00000000 pc=00000012..0000001f
+- DW_CFA_advance_loc: 1 to 00000013
++00000030 00000018 00000034 FDE cie=00000000 pc=0000004a..00000057
++ DW_CFA_advance_loc: 1 to 0000004b
+ DW_CFA_def_cfa_offset: 8
+- DW_CFA_offset: r6 at cfa-8
+- DW_CFA_advance_loc: 2 to 00000015
+- DW_CFA_def_cfa_reg: r6
+- DW_CFA_advance_loc: 9 to 0000001e
+- DW_CFA_def_cfa_reg: r7
+- DW_CFA_nop
++ DW_CFA_offset: r5 at cfa-8
++ DW_CFA_advance_loc: 2 to 0000004d
++ DW_CFA_def_cfa_reg: r5
++ DW_CFA_advance_loc: 9 to 00000056
++ DW_CFA_def_cfa_reg: r4
+
+-00000048 00000014 0000004c FDE cie=00000000 pc=0000001f..0000002f
+- DW_CFA_advance_loc: 2 to 00000021
+- DW_CFA_def_cfa_reg: r1
+- DW_CFA_advance_loc: 13 to 0000002e
+- DW_CFA_def_cfa: r7 ofs 4
+- DW_CFA_nop
++0000004c 00000014 00000050 FDE cie=00000000 pc=00000073..00000083
++ DW_CFA_advance_loc: 2 to 00000075
++ DW_CFA_def_cfa_reg: r3
++ DW_CFA_advance_loc: 13 to 00000082
++ DW_CFA_def_cfa: r4 ofs 4
+
+-00000060 00000010 00000064 FDE cie=00000000 pc=0000002f..00000035
+- DW_CFA_nop
++00000064 00000010 00000068 FDE cie=00000000 pc=0000009b..000000a1
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+-00000074 00000010 00000078 FDE cie=00000000 pc=00000035..00000044
+- DW_CFA_nop
++00000078 00000010 0000007c FDE cie=00000000 pc=000000b5..000000c4
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+--- gas/testsuite/gas/cfi/cfi-x86_64.d 20 May 2003 14:31:44 -0000 1.2
++++ gas/testsuite/gas/cfi/cfi-x86_64.d 27 May 2003 16:52:49 -0000 1.3
+@@ -1,68 +1,51 @@
+ #readelf: -wf
+ #name: CFI on x86-64
+-
+ The section .eh_frame contains:
+
+ 00000000 00000014 00000000 CIE
+ Version: 1
+- Augmentation: ""
++ Augmentation: "zR"
+ Code alignment factor: 1
+ Data alignment factor: -8
+ Return address column: 16
++ Augmentation data: 1b
+
+ DW_CFA_def_cfa: r7 ofs 8
+ DW_CFA_offset: r16 at cfa-8
+ DW_CFA_nop
+ DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000018 0000001c 0000001c FDE cie=00000000 pc=00000000..00000014
+- DW_CFA_advance_loc: 7 to 00000007
++00000018 00000014 0000001c FDE cie=00000000 pc=00000020..00000034
++ DW_CFA_advance_loc: 7 to 00000027
+ DW_CFA_def_cfa_offset: 4668
+- DW_CFA_advance_loc: 12 to 00000013
++ DW_CFA_advance_loc: 12 to 00000033
+ DW_CFA_def_cfa_offset: 8
+- DW_CFA_nop
+
+-00000038 00000024 0000003c FDE cie=00000000 pc=00000000..0000000f
+- DW_CFA_advance_loc: 1 to 00000001
++00000030 0000001c 00000034 FDE cie=00000000 pc=00000038..00000047
++ DW_CFA_advance_loc: 1 to 00000039
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r6 at cfa-16
+- DW_CFA_advance_loc: 3 to 00000004
++ DW_CFA_advance_loc: 3 to 0000003c
+ DW_CFA_def_cfa_reg: r6
+- DW_CFA_advance_loc: 10 to 0000000e
++ DW_CFA_advance_loc: 10 to 00000046
+ DW_CFA_def_cfa: r7 ofs 8
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+- DW_CFA_nop
+
+-00000060 0000001c 00000064 FDE cie=00000000 pc=00000000..00000013
+- DW_CFA_advance_loc: 3 to 00000003
++00000050 00000014 00000054 FDE cie=00000000 pc=00000058..0000006b
++ DW_CFA_advance_loc: 3 to 0000005b
+ DW_CFA_def_cfa_reg: r12
+- DW_CFA_advance_loc: 15 to 00000012
++ DW_CFA_advance_loc: 15 to 0000006a
+ DW_CFA_def_cfa_reg: r7
+ DW_CFA_nop
+- DW_CFA_nop
+
+-00000080 0000001c 00000084 FDE cie=00000000 pc=00000000..00000006
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
++00000068 00000010 0000006c FDE cie=00000000 pc=00000070..00000076
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+
+-000000a0 0000001c 000000a4 FDE cie=00000000 pc=00000000..00000012
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
++0000007c 00000010 00000080 FDE cie=00000000 pc=00000084..00000096
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+--- gas/testsuite/gas/cfi/cfi.exp 20 May 2003 08:01:19 -0000 1.1
++++ gas/testsuite/gas/cfi/cfi.exp 31 May 2003 19:36:45 -0000 1.3
+@@ -5,3 +5,16 @@ if [istarget "x86_64-*"] then {
+ if [istarget "i?86-*"] then {
+ run_dump_test "cfi-i386"
+ }
++
++if { [istarget alpha*-*-*] } then {
++
++ set elf [expr [istarget *-*-elf*] \
++ || [istarget *-*-linux*] \
++ || [istarget *-*-freebsd*] \
++ || [istarget *-*-netbsd*] ]
++
++ if $elf {
++ run_dump_test "cfi-alpha-1"
++ run_dump_test "cfi-alpha-2"
++ }
++}
+--- gas/testsuite/gas/cfi/cfi-alpha-1.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-1.d 2003-05-29 23:01:12.000000000 -0400
+@@ -0,0 +1,26 @@
++#readelf: -wf
++#name: CFI on alpha
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: 4
++ Data alignment factor: -8
++ Return address column: 26
++ Augmentation data: 1b
++
++ DW_CFA_def_cfa_reg: r30
++ DW_CFA_nop
++
++00000014 0000001c 00000018 FDE cie=00000000 pc=0000001c..00000050
++ DW_CFA_advance_loc: 24 to 00000034
++ DW_CFA_def_cfa: r15 ofs 32
++ DW_CFA_offset: r26 at cfa-32
++ DW_CFA_offset: r9 at cfa-24
++ DW_CFA_offset: r15 at cfa-16
++ DW_CFA_offset: r34 at cfa-8
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++
+--- gas/testsuite/gas/cfi/cfi-alpha-1.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-1.s 2003-05-29 23:01:12.000000000 -0400
+@@ -0,0 +1,28 @@
++ .file 1 "z.c"
++ .set noat
++ .set noreorder
++.text
++ .align 4
++ .globl f
++ .ent f
++$f..ng:
++f:
++ .frame $15,32,$26,0
++ .mask 0x4008200,-32
++ .fmask 0x4,-8
++ lda $30,-32($30)
++ stq $26,0($30)
++ stq $9,8($30)
++ stq $15,16($30)
++ stt $f2,24($30)
++ mov $30,$15
++ .prologue 0
++ mov $15,$30
++ ldq $26,0($30)
++ ldq $9,8($30)
++ ldt $f2,24($30)
++ ldq $15,16($30)
++ lda $30,32($30)
++ ret $31,($26),1
++ .end f
++ .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.1)"
+--- gas/testsuite/gas/cfi/cfi-alpha-2.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-2.d 2003-05-31 15:36:45.000000000 -0400
+@@ -0,0 +1,9 @@
++#objdump: -r -j .eh_frame
++#name: CFI on alpha, 2
++
++.*: file format elf64-alpha
++
++RELOCATION RECORDS FOR \[\.eh_frame\]:
++OFFSET TYPE VALUE
++0*000001c SREL32 \.text
++0*0000030 SREL32 \.text\+0x0*0000004
+--- gas/testsuite/gas/cfi/cfi-alpha-2.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-2.s 2003-05-31 15:36:45.000000000 -0400
+@@ -0,0 +1,14 @@
++ .text
++ .ent foo
++foo:
++ .frame $30, 0, $26, 0
++ .prologue 1
++ ret
++ .end foo
++
++ .ent bar
++bar:
++ .frame $30, 0, $26, 0
++ .prologue 1
++ ret
++ .end bar
+--- gas/testsuite/gas/cfi/cfi-i386-2.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-i386-2.d 2003-05-27 12:52:49.000000000 -0400
+@@ -0,0 +1,26 @@
++#readelf: -wf
++#name: CFI on i386, 2
++The section .eh_frame contains:
++
++00000000 00000014 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: 1
++ Data alignment factor: -4
++ Return address column: 8
++ Augmentation data: 1b
++
++ DW_CFA_def_cfa: r4 ofs 4
++ DW_CFA_offset: r8 at cfa-4
++ DW_CFA_nop
++ DW_CFA_nop
++
++00000018 00000018 0000001c FDE cie=00000000 pc=00000020..00000029
++ DW_CFA_advance_loc: 1 to 00000021
++ DW_CFA_def_cfa_offset: 8
++ DW_CFA_offset: r5 at cfa-8
++ DW_CFA_advance_loc: 4 to 00000025
++ DW_CFA_offset: r3 at cfa-12
++ DW_CFA_def_cfa_offset: 12
++ DW_CFA_nop
++
+--- gas/testsuite/gas/cfi/cfi-i386-2.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-i386-2.s 2003-05-27 12:52:49.000000000 -0400
+@@ -0,0 +1,17 @@
++ .text
++ .globl foo
++ .type foo,@function
++ .cfi_startproc
++foo:
++ push %ebp
++ .cfi_adjust_cfa_offset 4
++ .cfi_offset %ebp, -8
++ .align 4
++ push %ebx
++ .cfi_offset %ebx, -12
++ .cfi_adjust_cfa_offset 4
++ nop
++ pop %ebx
++ pop %ebp
++ ret
++ .cfi_endproc
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi2.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi2.patch
new file mode 100644
index 000000000000..374fe9418bb1
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi2.patch
@@ -0,0 +1,651 @@
+2003-06-05 Michal Ludvig <mludvig@suse.cz>
+
+ * dw2gencfi.c (cfi_add_CFA_insn, cfi_add_CFA_insn_reg)
+ (cfi_add_CFA_insn_reg_reg, cfi_add_CFA_insn_reg_offset): New.
+ (cfi_add_CFA_offset, cfi_add_CFA_def_cfa)
+ (cfi_add_CFA_register, cfi_add_CFA_def_cfa_register)
+ (cfi_add_CFA_def_cfa_offset): Use cfi_add_CFA_insn_*().
+ (cfi_add_CFA_restore, cfi_add_CFA_undefined)
+ (cfi_add_CFA_same_value, cfi_add_CFA_remember_state)
+ (cfi_add_CFA_restore_state, cfi_add_CFA_nop): New.
+ (cfi_pseudo_table): New directives .cfi_return_column,
+ .cfi_restore, .cfi_undefined, .cfi_same_value,
+ .cfi_remember_state, .cfi_restore_state, .cfi_nop.
+ (dot_cfi, output_cfi_insn): Handle new directives.
+ * dw2gencfi.h (cfi_add_CFA_restore, cfi_add_CFA_undefined)
+ (cfi_add_CFA_same_value, cfi_add_CFA_remember_state)
+ (cfi_add_CFA_restore_state, cfi_add_CFA_nop): New prototypes.
+
+2003-06-04 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c (output_cfi_insn): Fix typo for negative offsets.
+
+ * dw2gencfi.c (cfi_finish): Set .eh_frame read-only.
+
+2003-06-04 Richard Henderson <rth@redhat.com>
+
+ * config/tc-alpha.c (s_alpha_usepv): New.
+ (md_pseudo_table): Add it.
+ (alpha_cfi_frame_initial_instructions): New.
+ * config/tc-alpha.h (TARGET_USE_CFIPOP): New.
+ (tc_cfi_frame_initial_instructions): New.
+ * doc/c-alpha.texi: Document .usepv.
+
+testsuite/
+2003-06-04 Richard Henderson <rth@redhat.com>
+
+ * gas/alpha/elf-usepv-1.[sd]: New.
+ * gas/alpha/elf-usepv-2.[sd]: New.
+ * gas/alpha/alpha.exp: Run them.
+ * gas/cfi/cfi-alpha-3.[sd]: New.
+ * gas/cfi/cfi.exp: Run it.
+
+--- gas/dw2gencfi.c 2 Jun 2003 22:48:59 -0000 1.7
++++ gas/dw2gencfi.c 5 Jun 2003 09:23:47 -0000 1.10
+@@ -164,6 +164,54 @@ cfi_set_return_column (unsigned regno)
+ cur_fde_data->return_column = regno;
+ }
+
++/* Universal functions to store new instructions. */
++
++static void
++cfi_add_CFA_insn(int insn)
++{
++ struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
++
++ insn_ptr->insn = insn;
++}
++
++static void
++cfi_add_CFA_insn_reg (int insn, unsigned regno)
++{
++ struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
++
++ insn_ptr->insn = insn;
++ insn_ptr->u.r = regno;
++}
++
++static void
++cfi_add_CFA_insn_offset (int insn, offsetT offset)
++{
++ struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
++
++ insn_ptr->insn = insn;
++ insn_ptr->u.i = offset;
++}
++
++static void
++cfi_add_CFA_insn_reg_reg (int insn, unsigned reg1, unsigned reg2)
++{
++ struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
++
++ insn_ptr->insn = insn;
++ insn_ptr->u.rr.reg1 = reg1;
++ insn_ptr->u.rr.reg2 = reg2;
++}
++
++static void
++cfi_add_CFA_insn_reg_offset (int insn, unsigned regno, offsetT offset)
++{
++ struct cfi_insn_data *insn_ptr = alloc_cfi_insn_data ();
++
++ insn_ptr->insn = insn;
++ insn_ptr->u.ri.reg = regno;
++ insn_ptr->u.ri.offset = offset;
++}
++
+ /* Add a CFI insn to advance the PC from the last address to LABEL. */
+
+ void
+@@ -183,11 +231,7 @@ cfi_add_advance_loc (symbolS *label)
+ void
+ cfi_add_CFA_offset (unsigned regno, offsetT offset)
+ {
+- struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+-
+- insn->insn = DW_CFA_offset;
+- insn->u.ri.reg = regno;
+- insn->u.ri.offset = offset;
++ cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
+ }
+
+ /* Add a DW_CFA_def_cfa record to the CFI data. */
+@@ -195,12 +239,7 @@ cfi_add_CFA_offset (unsigned regno, offs
+ void
+ cfi_add_CFA_def_cfa (unsigned regno, offsetT offset)
+ {
+- struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+-
+- insn->insn = DW_CFA_def_cfa;
+- insn->u.ri.reg = regno;
+- insn->u.ri.offset = offset;
+-
++ cfi_add_CFA_insn_reg_offset (DW_CFA_def_cfa, regno, offset);
+ cur_cfa_offset = offset;
+ }
+
+@@ -209,11 +248,7 @@ cfi_add_CFA_def_cfa (unsigned regno, off
+ void
+ cfi_add_CFA_register (unsigned reg1, unsigned reg2)
+ {
+- struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+-
+- insn->insn = DW_CFA_register;
+- insn->u.rr.reg1 = reg1;
+- insn->u.rr.reg2 = reg2;
++ cfi_add_CFA_insn_reg_reg (DW_CFA_register, reg1, reg2);
+ }
+
+ /* Add a DW_CFA_def_cfa_register record to the CFI data. */
+@@ -221,10 +256,7 @@ cfi_add_CFA_register (unsigned reg1, uns
+ void
+ cfi_add_CFA_def_cfa_register (unsigned regno)
+ {
+- struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+-
+- insn->insn = DW_CFA_def_cfa_register;
+- insn->u.r = regno;
++ cfi_add_CFA_insn_reg (DW_CFA_def_cfa_register, regno);
+ }
+
+ /* Add a DW_CFA_def_cfa_offset record to the CFI data. */
+@@ -232,14 +264,46 @@ cfi_add_CFA_def_cfa_register (unsigned r
+ void
+ cfi_add_CFA_def_cfa_offset (offsetT offset)
+ {
+- struct cfi_insn_data *insn = alloc_cfi_insn_data ();
+-
+- insn->insn = DW_CFA_def_cfa_offset;
+- insn->u.i = offset;
+-
++ cfi_add_CFA_insn_offset (DW_CFA_def_cfa_offset, offset);
+ cur_cfa_offset = offset;
+ }
+
++void
++cfi_add_CFA_restore (unsigned regno)
++{
++ cfi_add_CFA_insn_reg (DW_CFA_restore, regno);
++}
++
++void
++cfi_add_CFA_undefined (unsigned regno)
++{
++ cfi_add_CFA_insn_reg (DW_CFA_undefined, regno);
++}
++
++void
++cfi_add_CFA_same_value (unsigned regno)
++{
++ cfi_add_CFA_insn_reg (DW_CFA_same_value, regno);
++}
++
++void
++cfi_add_CFA_remember_state (void)
++{
++ cfi_add_CFA_insn (DW_CFA_remember_state);
++}
++
++void
++cfi_add_CFA_restore_state (void)
++{
++ cfi_add_CFA_insn (DW_CFA_restore_state);
++}
++
++void
++cfi_add_CFA_nop (void)
++{
++ cfi_add_CFA_insn (DW_CFA_nop);
++}
++
+
+ /* Parse CFI assembler directives. */
+
+@@ -248,7 +312,8 @@ static void dot_cfi_startproc (int);
+ static void dot_cfi_endproc (int);
+
+ /* Fake CFI type; outside the byte range of any real CFI insn. */
+-#define CFI_adjust_cfa_offset 0x100
++#define CFI_adjust_cfa_offset 0x100
++#define CFI_return_column 0x101
+
+ const pseudo_typeS cfi_pseudo_table[] =
+ {
+@@ -260,6 +325,13 @@ const pseudo_typeS cfi_pseudo_table[] =
+ { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
+ { "cfi_offset", dot_cfi, DW_CFA_offset },
+ { "cfi_register", dot_cfi, DW_CFA_register },
++ { "cfi_return_column", dot_cfi, CFI_return_column },
++ { "cfi_restore", dot_cfi, DW_CFA_restore },
++ { "cfi_undefined", dot_cfi, DW_CFA_undefined },
++ { "cfi_same_value", dot_cfi, DW_CFA_same_value },
++ { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
++ { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
++ { "cfi_nop", dot_cfi, DW_CFA_nop },
+ { NULL, NULL, 0 }
+ };
+
+@@ -343,46 +415,74 @@ dot_cfi (int arg)
+
+ switch (arg)
+ {
+- /* Instructions that take two arguments (register, integer). */
+ case DW_CFA_offset:
+- case DW_CFA_def_cfa:
+ reg1 = cfi_parse_reg ();
+ cfi_parse_separator ();
+ offset = cfi_parse_const ();
++ cfi_add_CFA_offset (reg1, offset);
++ break;
+
+- if (arg == DW_CFA_def_cfa)
+- cfi_add_CFA_def_cfa (reg1, offset);
+- else
+- cfi_add_CFA_offset (reg1, offset);
++ case DW_CFA_def_cfa:
++ reg1 = cfi_parse_reg ();
++ cfi_parse_separator ();
++ offset = cfi_parse_const ();
++ cfi_add_CFA_def_cfa (reg1, offset);
+ break;
+
+- /* Instructions that take two arguments (register, register). */
+ case DW_CFA_register:
+ reg1 = cfi_parse_reg ();
+ cfi_parse_separator ();
+ reg2 = cfi_parse_reg ();
+-
+ cfi_add_CFA_register (reg1, reg2);
+ break;
+
+- /* Instructions that take one register argument. */
+ case DW_CFA_def_cfa_register:
+ reg1 = cfi_parse_reg ();
+ cfi_add_CFA_def_cfa_register (reg1);
+ break;
+
+- /* Instructions that take one integer argument. */
+ case DW_CFA_def_cfa_offset:
+ offset = cfi_parse_const ();
+ cfi_add_CFA_def_cfa_offset (offset);
+ break;
+
+- /* Special handling for pseudo-instruction. */
+ case CFI_adjust_cfa_offset:
+ offset = cfi_parse_const ();
+ cfi_add_CFA_def_cfa_offset (cur_cfa_offset + offset);
+ break;
+
++ case DW_CFA_restore:
++ reg1 = cfi_parse_reg ();
++ cfi_add_CFA_restore (reg1);
++ break;
++
++ case DW_CFA_undefined:
++ reg1 = cfi_parse_reg ();
++ cfi_add_CFA_undefined (reg1);
++ break;
++
++ case DW_CFA_same_value:
++ reg1 = cfi_parse_reg ();
++ cfi_add_CFA_same_value (reg1);
++ break;
++
++ case CFI_return_column:
++ reg1 = cfi_parse_reg ();
++ cfi_set_return_column (reg1);
++ break;
++
++ case DW_CFA_remember_state:
++ cfi_add_CFA_remember_state ();
++ break;
++
++ case DW_CFA_restore_state:
++ cfi_add_CFA_restore_state ();
++ break;
++
++ case DW_CFA_nop:
++ cfi_add_CFA_nop ();
++ break;
++
+ default:
+ abort ();
+ }
+@@ -553,8 +653,10 @@ output_cfi_insn (struct cfi_insn_data *i
+ break;
+
+ case DW_CFA_def_cfa_register:
+- out_one (DW_CFA_def_cfa_register);
+- out_uleb128 (insn->u.i);
++ case DW_CFA_undefined:
++ case DW_CFA_same_value:
++ out_one (insn->insn);
++ out_uleb128 (insn->u.r);
+ break;
+
+ case DW_CFA_def_cfa_offset:
+@@ -571,12 +673,25 @@ output_cfi_insn (struct cfi_insn_data *i
+ }
+ break;
+
++ case DW_CFA_restore:
++ regno = insn->u.r;
++ if (regno <= 0x3F)
++ {
++ out_one (DW_CFA_restore + regno);
++ }
++ else
++ {
++ out_one (DW_CFA_restore_extended);
++ out_uleb128 (regno);
++ }
++ break;
++
+ case DW_CFA_offset:
+ regno = insn->u.ri.reg;
+ offset = insn->u.ri.offset / DWARF2_CIE_DATA_ALIGNMENT;
+ if (offset < 0)
+ {
+- out_one (DW_CFA_offset_extended);
++ out_one (DW_CFA_offset_extended_sf);
+ out_uleb128 (regno);
+ out_sleb128 (offset);
+ }
+@@ -599,8 +714,10 @@ output_cfi_insn (struct cfi_insn_data *i
+ out_uleb128 (insn->u.rr.reg2);
+ break;
+
++ case DW_CFA_remember_state:
++ case DW_CFA_restore_state:
+ case DW_CFA_nop:
+- out_one (DW_CFA_nop);
++ out_one (insn->insn);
+ break;
+
+ default:
+@@ -722,6 +839,9 @@ select_cie_for_fde (struct fde_entry *fd
+ break;
+
+ case DW_CFA_def_cfa_register:
++ case DW_CFA_restore:
++ case DW_CFA_undefined:
++ case DW_CFA_same_value:
+ if (i->u.r != j->u.r)
+ goto fail;
+ break;
+@@ -785,7 +905,7 @@ cfi_finish (void)
+ cfi_seg = subseg_new (".eh_frame", 0);
+ #ifdef BFD_ASSEMBLER
+ bfd_set_section_flags (stdoutput, cfi_seg,
+- SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
++ SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
+ #endif
+ subseg_set (cfi_seg, 0);
+ record_alignment (cfi_seg, 2);
+--- gas/dw2gencfi.h 27 May 2003 16:52:46 -0000 1.2
++++ gas/dw2gencfi.h 5 Jun 2003 09:23:47 -0000 1.3
+@@ -37,10 +37,17 @@ extern void cfi_new_fde (struct symbol *
+ extern void cfi_end_fde (struct symbol *);
+ extern void cfi_set_return_column (unsigned);
+ extern void cfi_add_advance_loc (struct symbol *);
++
+ extern void cfi_add_CFA_offset (unsigned, offsetT);
+ extern void cfi_add_CFA_def_cfa (unsigned, offsetT);
+ extern void cfi_add_CFA_register (unsigned, unsigned);
+ extern void cfi_add_CFA_def_cfa_register (unsigned);
+ extern void cfi_add_CFA_def_cfa_offset (offsetT);
++extern void cfi_add_CFA_restore (unsigned);
++extern void cfi_add_CFA_undefined (unsigned);
++extern void cfi_add_CFA_same_value (unsigned);
++extern void cfi_add_CFA_remember_state (void);
++extern void cfi_add_CFA_restore_state (void);
++extern void cfi_add_CFA_nop (void);
+
+ #endif /* DW2GENCFI_H */
+--- gas/config/tc-alpha.c 30 May 2003 03:01:11 -0000 1.57
++++ gas/config/tc-alpha.c 5 Jun 2003 03:27:03 -0000 1.58
+@@ -267,6 +267,7 @@ static void s_alpha_file PARAMS ((int));
+ static void s_alpha_loc PARAMS ((int));
+ static void s_alpha_stab PARAMS ((int));
+ static void s_alpha_coff_wrapper PARAMS ((int));
++static void s_alpha_usepv PARAMS ((int));
+ #endif
+ #ifdef OBJ_EVAX
+ static void s_alpha_section PARAMS ((int));
+@@ -4822,8 +4823,65 @@ alpha_elf_md_end (void)
+ cfi_end_fde (p->func_end_sym);
+ }
+ }
++
++static void
++s_alpha_usepv (int unused ATTRIBUTE_UNUSED)
++{
++ char *name, name_end;
++ char *which, which_end;
++ symbolS *sym;
++ int other;
++
++ name = input_line_pointer;
++ name_end = get_symbol_end ();
++
++ if (! is_name_beginner (*name))
++ {
++ as_bad (_(".usepv directive has no name"));
++ *input_line_pointer = name_end;
++ ignore_rest_of_line ();
++ return;
++ }
++
++ sym = symbol_find_or_make (name);
++ *input_line_pointer++ = name_end;
++
++ if (name_end != ',')
++ {
++ as_bad (_(".usepv directive has no type"));
++ ignore_rest_of_line ();
++ return;
++ }
++
++ SKIP_WHITESPACE ();
++ which = input_line_pointer;
++ which_end = get_symbol_end ();
++
++ if (strcmp (which, "no") == 0)
++ other = STO_ALPHA_NOPV;
++ else if (strcmp (which, "std") == 0)
++ other = STO_ALPHA_STD_GPLOAD;
++ else
++ {
++ as_bad (_("unknown argument for .usepv"));
++ other = 0;
++ }
++
++ *input_line_pointer = which_end;
++ demand_empty_rest_of_line ();
++
++ S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
++}
+ #endif /* OBJ_ELF */
+
++/* Standard calling conventions leaves the CFA at $30 on entry. */
++
++void
++alpha_cfi_frame_initial_instructions ()
++{
++ cfi_add_CFA_def_cfa_register (30);
++}
++
+ #ifdef OBJ_EVAX
+
+ /* Handle the section specific pseudo-op. */
+@@ -5669,6 +5727,7 @@ const pseudo_typeS md_pseudo_table[] = {
+ {"loc", s_alpha_loc, 9},
+ {"stabs", s_alpha_stab, 's'},
+ {"stabn", s_alpha_stab, 'n'},
++ {"usepv", s_alpha_usepv, 0},
+ /* COFF debugging related pseudos. */
+ {"begin", s_alpha_coff_wrapper, 0},
+ {"bend", s_alpha_coff_wrapper, 1},
+--- gas/config/tc-alpha.h 30 May 2003 03:01:11 -0000 1.17
++++ gas/config/tc-alpha.h 5 Jun 2003 03:27:03 -0000 1.18
+@@ -161,6 +161,11 @@ do { \
+ (long) FIX->tc_fix_data.next_reloc); \
+ } while (0)
+
++#define TARGET_USE_CFIPOP 1
++
++#define tc_cfi_frame_initial_instructions alpha_cfi_frame_initial_instructions
++extern void alpha_cfi_frame_initial_instructions(void);
++
+ #define DWARF2_LINE_MIN_INSN_LENGTH 4
+ #define DWARF2_DEFAULT_RETURN_COLUMN 26
+ #define DWARF2_CIE_DATA_ALIGNMENT -8
+--- gas/doc/c-alpha.texi 19 Dec 2002 01:11:31 -0000 1.4
++++ gas/doc/c-alpha.texi 5 Jun 2003 03:27:03 -0000 1.5
+@@ -379,6 +379,18 @@ to perform a load of the GP register; 2
+ used in some non-standard way and so the linker cannot elide the load of
+ the procedure vector during relaxation.
+
++@item .usepv @var{function}, @var{which}
++Used to indicate the use of the @code{$27} register, similar to
++@code{.prologue}, but without the other semantics of needing to
++be inside an open @code{.ent}/@code{.end} block.
++
++The @var{which} argument should be either @code{no}, indicating that
++@code{$27} is not used, or @code{std}, indicating that the first two
++instructions of the function perform a GP load.
++
++One might use this directive instead of @code{.prologue} if you are
++also using dwarf2 CFI directives.
++
+ @item .gprel32 @var{expression}
+ Computes the difference between the address in @var{expression} and the
+ GP for the current object file, and stores it in 4 bytes. In addition
+
+--- gas/testsuite/gas/alpha/alpha.exp 7 Nov 2002 00:42:18 -0000 1.6
++++ gas/testsuite/gas/alpha/alpha.exp 5 Jun 2003 03:27:03 -0000 1.7
+@@ -34,6 +34,8 @@ if { [istarget alpha*-*-*] } then {
+ run_dump_test "elf-tls-1"
+ run_list_test "elf-tls-2" ""
+ run_list_test "elf-tls-3" ""
++ run_dump_test "elf-usepv-1"
++ run_list_test "elf-usepv-2" ""
+ }
+
+ run_dump_test "fp"
+--- gas/testsuite/gas/cfi/cfi.exp 31 May 2003 19:36:45 -0000 1.3
++++ gas/testsuite/gas/cfi/cfi.exp 5 Jun 2003 03:27:03 -0000 1.4
+@@ -16,5 +16,6 @@ if { [istarget alpha*-*-*] } then {
+ if $elf {
+ run_dump_test "cfi-alpha-1"
+ run_dump_test "cfi-alpha-2"
++ run_dump_test "cfi-alpha-3"
+ }
+ }
+--- gas/testsuite/gas/alpha/elf-usepv-1.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/alpha/elf-usepv-1.d 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1,11 @@
++#objdump: --syms
++#name: alpha elf-usepv-1
++
++.*: file format elf64-alpha
++
++SYMBOL TABLE:
++0*0000000 l d .text 0*0000000
++0*0000000 l d .data 0*0000000
++0*0000000 l d .bss 0*0000000
++0*0000000 l .text 0*0000000 0x80 foo
++0*0000004 l .text 0*0000000 0x88 bar
+--- gas/testsuite/gas/alpha/elf-usepv-1.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/alpha/elf-usepv-1.s 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1,6 @@
++ .usepv foo, no
++foo:
++ nop
++ .usepv bar, std
++bar:
++ nop
+--- gas/testsuite/gas/alpha/elf-usepv-2.l 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/alpha/elf-usepv-2.l 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1,2 @@
++.*: Assembler messages:
++.*:1: Error: unknown argument for .usepv
+--- gas/testsuite/gas/alpha/elf-usepv-2.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/alpha/elf-usepv-2.s 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1 @@
++ .usepv foo, bar
+--- gas/testsuite/gas/cfi/cfi-alpha-3.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-3.d 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1,32 @@
++#readelf: -wf
++#name: CFI on alpha, 3
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: 4
++ Data alignment factor: -8
++ Return address column: 26
++ Augmentation data: 1b
++
++ DW_CFA_def_cfa_reg: r30
++ DW_CFA_nop
++
++00000014 00000024 00000018 FDE cie=00000000 pc=0000001c..0000005c
++ DW_CFA_advance_loc: 4 to 00000020
++ DW_CFA_def_cfa_offset: 32
++ DW_CFA_advance_loc: 4 to 00000024
++ DW_CFA_offset: r26 at cfa-32
++ DW_CFA_advance_loc: 4 to 00000028
++ DW_CFA_offset: r9 at cfa-24
++ DW_CFA_advance_loc: 4 to 0000002c
++ DW_CFA_offset: r15 at cfa-16
++ DW_CFA_advance_loc: 4 to 00000030
++ DW_CFA_offset: r34 at cfa-8
++ DW_CFA_advance_loc: 4 to 00000034
++ DW_CFA_def_cfa_reg: r15
++ DW_CFA_advance_loc: 36 to 00000058
++ DW_CFA_def_cfa: r30 ofs 0
++ DW_CFA_nop
++
+--- gas/testsuite/gas/cfi/cfi-alpha-3.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-alpha-3.s 2003-06-04 23:27:03.000000000 -0400
+@@ -0,0 +1,37 @@
++ .file 1 "z.c"
++ .set noat
++ .set noreorder
++.text
++ .align 4
++ .globl f
++ .type f,@function
++ .usepv f,no
++ .cfi_startproc
++f:
++ lda $30,-32($30)
++ .cfi_adjust_cfa_offset 32
++ stq $26,0($30)
++ .cfi_offset $26, -32
++ stq $9,8($30)
++ .cfi_offset $9, -24
++ stq $15,16($30)
++ .cfi_offset $15, -16
++ stt $f2,24($30)
++ .cfi_offset $f2, -8
++ mov $30,$15
++ .cfi_def_cfa_register $15
++
++ nop
++ nop
++ nop
++
++ mov $15,$30
++ ldq $26,0($30)
++ ldq $9,8($30)
++ ldt $f2,24($30)
++ ldq $15,16($30)
++ lda $30,32($30)
++ .cfi_def_cfa $30, 0
++ ret $31,($26),1
++ .size f, .-f
++ .cfi_endproc
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi3.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi3.patch
new file mode 100644
index 000000000000..b8881c7c83c6
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi3.patch
@@ -0,0 +1,509 @@
+2003-06-11 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c (struct cfi_escape_data): New.
+ (cfi_add_CFA_nop): Remove.
+ (CFI_escape, dot_cfi_escape): New.
+ (dot_cfi): Remove nop.
+ (cfi_pseudo_table): Remove nop; add escape.
+ (output_cfi_insn): Likewise.
+ (select_cie_for_fde): Stop on escape.
+ * dw2gencfi.h (cfi_add_CFA_nop): Remove.
+ * read.c, read.h (do_parse_cons_expression): New.
+
+2003-06-07 Richard Henderson <rth@redhat.com>
+
+ * dw2gencfi.c (struct cfa_save_data, cfa_save_stack): New.
+ (cfi_add_CFA_offset): Detect invalid offsets.
+ (cfi_add_CFA_remember_state): Save cur_cfa_offset.
+ (cfi_add_CFA_restore_state): Restore it.
+ (CFI_rel_offset): New.
+ (cfi_pseudo_table): Add it.
+ (dot_cfi): Handle it.
+
+testsuite/
+2003-06-11 Richard Henderson <rth@redhat.com>
+
+ * gas/cfi/cfi-common-3.[ds]: New.
+ * gas/cfi/cfi.exp: Run it.
+
+2003-06-10 Alan Modra <amodra@bigpond.net.au>
+
+ * lib/gas-defs.exp (proc is_elf_format): Copy from ld testsuite.
+ * gas/cfi/cfi.exp: Use here. Only run tests when ELF.
+
+2003-06-07 Richard Henderson <rth@redhat.com>
+
+ * gas/cfi/cfi-common-1.d, gas/cfi/cfi-common-1.s: New.
+ * gas/cfi/cfi-common-2.d, gas/cfi/cfi-common-2.s: New.
+ * gas/cfi/cfi-diag-1.d, gas/cfi/cfi-diag-1.s: New.
+ * gas/cfi/cfi.exp: Run them.
+
+--- gas/dw2gencfi.c 5 Jun 2003 09:23:47 -0000 1.10
++++ gas/dw2gencfi.c 11 Jun 2003 23:16:57 -0000 1.12
+@@ -68,6 +68,11 @@ struct cfi_insn_data
+ symbolS *lab1;
+ symbolS *lab2;
+ } ll;
++
++ struct cfi_escape_data {
++ struct cfi_escape_data *next;
++ expressionS exp;
++ } *esc;
+ } u;
+ };
+
+@@ -102,6 +107,14 @@ static struct fde_entry **last_fde_data
+ /* List of CIEs so that they could be reused. */
+ static struct cie_entry *cie_root;
+
++/* Stack of old CFI data, for save/restore. */
++struct cfa_save_data
++{
++ struct cfa_save_data *next;
++ offsetT cfa_offset;
++};
++
++static struct cfa_save_data *cfa_save_stack;
+
+ /* Construct a new FDE structure and add it to the end of the fde list. */
+
+@@ -231,7 +244,14 @@ cfi_add_advance_loc (symbolS *label)
+ void
+ cfi_add_CFA_offset (unsigned regno, offsetT offset)
+ {
++ unsigned int abs_data_align;
++
+ cfi_add_CFA_insn_reg_offset (DW_CFA_offset, regno, offset);
++
++ abs_data_align = (DWARF2_CIE_DATA_ALIGNMENT < 0
++ ? -DWARF2_CIE_DATA_ALIGNMENT : DWARF2_CIE_DATA_ALIGNMENT);
++ if (offset % abs_data_align)
++ as_bad (_("register save offset not a multiple of %u"), abs_data_align);
+ }
+
+ /* Add a DW_CFA_def_cfa record to the CFI data. */
+@@ -289,31 +309,45 @@ cfi_add_CFA_same_value (unsigned regno)
+ void
+ cfi_add_CFA_remember_state (void)
+ {
++ struct cfa_save_data *p;
++
+ cfi_add_CFA_insn (DW_CFA_remember_state);
++
++ p = xmalloc (sizeof (*p));
++ p->cfa_offset = cur_cfa_offset;
++ p->next = cfa_save_stack;
++ cfa_save_stack = p;
+ }
+
+ void
+ cfi_add_CFA_restore_state (void)
+ {
++ struct cfa_save_data *p;
++
+ cfi_add_CFA_insn (DW_CFA_restore_state);
+-}
+
+-void
+-cfi_add_CFA_nop (void)
+-{
+- cfi_add_CFA_insn (DW_CFA_nop);
++ p = cfa_save_stack;
++ if (p)
++ {
++ cur_cfa_offset = p->cfa_offset;
++ cfa_save_stack = p->next;
++ free (p);
++ }
+ }
+
+
+ /* Parse CFI assembler directives. */
+
+ static void dot_cfi (int);
++static void dot_cfi_escape (int);
+ static void dot_cfi_startproc (int);
+ static void dot_cfi_endproc (int);
+
+ /* Fake CFI type; outside the byte range of any real CFI insn. */
+ #define CFI_adjust_cfa_offset 0x100
+ #define CFI_return_column 0x101
++#define CFI_rel_offset 0x102
++#define CFI_escape 0x103
+
+ const pseudo_typeS cfi_pseudo_table[] =
+ {
+@@ -324,6 +358,7 @@ const pseudo_typeS cfi_pseudo_table[] =
+ { "cfi_def_cfa_offset", dot_cfi, DW_CFA_def_cfa_offset },
+ { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
+ { "cfi_offset", dot_cfi, DW_CFA_offset },
++ { "cfi_rel_offset", dot_cfi, CFI_rel_offset },
+ { "cfi_register", dot_cfi, DW_CFA_register },
+ { "cfi_return_column", dot_cfi, CFI_return_column },
+ { "cfi_restore", dot_cfi, DW_CFA_restore },
+@@ -331,7 +366,7 @@ const pseudo_typeS cfi_pseudo_table[] =
+ { "cfi_same_value", dot_cfi, DW_CFA_same_value },
+ { "cfi_remember_state", dot_cfi, DW_CFA_remember_state },
+ { "cfi_restore_state", dot_cfi, DW_CFA_restore_state },
+- { "cfi_nop", dot_cfi, DW_CFA_nop },
++ { "cfi_escape", dot_cfi_escape, 0 },
+ { NULL, NULL, 0 }
+ };
+
+@@ -422,6 +457,13 @@ dot_cfi (int arg)
+ cfi_add_CFA_offset (reg1, offset);
+ break;
+
++ case CFI_rel_offset:
++ reg1 = cfi_parse_reg ();
++ cfi_parse_separator ();
++ offset = cfi_parse_const ();
++ cfi_add_CFA_offset (reg1, offset - cur_cfa_offset);
++ break;
++
+ case DW_CFA_def_cfa:
+ reg1 = cfi_parse_reg ();
+ cfi_parse_separator ();
+@@ -479,10 +521,6 @@ dot_cfi (int arg)
+ cfi_add_CFA_restore_state ();
+ break;
+
+- case DW_CFA_nop:
+- cfi_add_CFA_nop ();
+- break;
+-
+ default:
+ abort ();
+ }
+@@ -491,6 +529,39 @@ dot_cfi (int arg)
+ }
+
+ static void
++dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
++{
++ struct cfi_escape_data *head, **tail, *e;
++ struct cfi_insn_data *insn;
++
++ if (!cur_fde_data)
++ {
++ as_bad (_("CFI instruction used without previous .cfi_startproc"));
++ return;
++ }
++
++ /* If the last address was not at the current PC, advance to current. */
++ if (symbol_get_frag (last_address) != frag_now
++ || S_GET_VALUE (last_address) != frag_now_fix ())
++ cfi_add_advance_loc (symbol_temp_new_now ());
++
++ tail = &head;
++ do
++ {
++ e = xmalloc (sizeof (*e));
++ do_parse_cons_expression (&e->exp, 1);
++ *tail = e;
++ tail = &e->next;
++ }
++ while (*input_line_pointer++ == ',');
++ *tail = NULL;
++
++ insn = alloc_cfi_insn_data ();
++ insn->insn = CFI_escape;
++ insn->u.esc = head;
++}
++
++static void
+ dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED)
+ {
+ int simple = 0;
+@@ -716,10 +787,17 @@ output_cfi_insn (struct cfi_insn_data *i
+
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
+- case DW_CFA_nop:
+ out_one (insn->insn);
+ break;
+
++ case CFI_escape:
++ {
++ struct cfi_escape_data *e;
++ for (e = insn->u.esc; e ; e = e->next)
++ emit_expr (&e->exp, 1);
++ break;
++ }
++
+ default:
+ abort ();
+ }
+@@ -850,6 +928,10 @@ select_cie_for_fde (struct fde_entry *fd
+ if (i->u.i != j->u.i)
+ goto fail;
+ break;
++
++ case CFI_escape:
++ /* Don't bother matching these for now. */
++ goto fail;
+
+ default:
+ abort ();
+--- gas/dw2gencfi.h 5 Jun 2003 09:23:47 -0000 1.3
++++ gas/dw2gencfi.h 11 Jun 2003 23:16:57 -0000 1.4
+@@ -48,6 +48,5 @@ extern void cfi_add_CFA_undefined (unsig
+ extern void cfi_add_CFA_same_value (unsigned);
+ extern void cfi_add_CFA_remember_state (void);
+ extern void cfi_add_CFA_restore_state (void);
+-extern void cfi_add_CFA_nop (void);
+
+ #endif /* DW2GENCFI_H */
+--- gas/read.c 2 Jun 2003 22:48:58 -0000 1.63
++++ gas/read.c 11 Jun 2003 23:16:57 -0000 1.64
+@@ -3346,6 +3346,13 @@ parse_repeat_cons PARAMS ((expressionS *
+ #endif
+ #endif
+
++void
++do_parse_cons_expression (expressionS *exp, int nbytes)
++{
++ TC_PARSE_CONS_EXPRESSION (exp, nbytes);
++}
++
++
+ /* Worker to do .byte etc statements.
+ Clobbers input_line_pointer and checks end-of-line. */
+
+--- gas/read.h 3 May 2003 06:10:59 -0000 1.17
++++ gas/read.h 11 Jun 2003 23:16:57 -0000 1.18
+@@ -133,6 +133,7 @@ extern void stabs_generate_asm_func PARA
+ extern void stabs_generate_asm_endfunc PARAMS ((const char *, const char *));
+ extern void do_repeat PARAMS((int,const char *,const char *));
+ extern void end_repeat PARAMS((int));
++extern void do_parse_cons_expression PARAMS ((expressionS *, int));
+
+ extern void generate_lineno_debug PARAMS ((void));
+
+--- gas/testsuite/gas/cfi/cfi.exp 5 Jun 2003 03:27:03 -0000 1.4
++++ gas/testsuite/gas/cfi/cfi.exp 11 Jun 2003 23:16:58 -0000 1.7
+@@ -1,21 +1,37 @@
++# ??? This probably shouldn't be replicated here...
++proc run_list_test { name opts } {
++ global srcdir subdir
++ set testname "cfi $name"
++ set file $srcdir/$subdir/$name
++ gas_run ${name}.s $opts ">&dump.out"
++ if { [regexp_diff "dump.out" "${file}.l"] } then {
++ fail $testname
++ verbose "output is [file_contents "dump.out"]" 2
++ return
++ }
++ pass $testname
++}
++
++if ![is_elf_format] then {
++ return
++}
++
+ if [istarget "x86_64-*"] then {
+ run_dump_test "cfi-x86_64"
+-}
+
+-if [istarget "i?86-*"] then {
++} elseif [istarget "i?86-*"] then {
+ run_dump_test "cfi-i386"
+-}
+
+-if { [istarget alpha*-*-*] } then {
++} elseif { [istarget alpha*-*-*] } then {
++ run_dump_test "cfi-alpha-1"
++ run_dump_test "cfi-alpha-2"
++ run_dump_test "cfi-alpha-3"
+
+- set elf [expr [istarget *-*-elf*] \
+- || [istarget *-*-linux*] \
+- || [istarget *-*-freebsd*] \
+- || [istarget *-*-netbsd*] ]
+-
+- if $elf {
+- run_dump_test "cfi-alpha-1"
+- run_dump_test "cfi-alpha-2"
+- run_dump_test "cfi-alpha-3"
+- }
++} else {
++ return
+ }
++
++run_list_test "cfi-diag-1" ""
++run_dump_test "cfi-common-1"
++run_dump_test "cfi-common-2"
++run_dump_test "cfi-common-3"
+--- gas/testsuite/lib/gas-defs.exp 16 May 2003 16:30:25 -0000 1.12
++++ gas/testsuite/lib/gas-defs.exp 10 Jun 2003 13:31:59 -0000 1.13
+@@ -182,6 +182,43 @@ proc gas_init { args } {
+ return
+ }
+
++#
++# is_elf_format
++# true if the object format is known to be ELF
++#
++proc is_elf_format {} {
++ if { ![istarget *-*-sysv4*] \
++ && ![istarget *-*-unixware*] \
++ && ![istarget *-*-elf*] \
++ && ![istarget *-*-eabi*] \
++ && ![istarget hppa*64*-*-hpux*] \
++ && ![istarget *-*-linux*] \
++ && ![istarget *-*-irix5*] \
++ && ![istarget *-*-irix6*] \
++ && ![istarget *-*-netbsd*] \
++ && ![istarget *-*-solaris2*] } {
++ return 0
++ }
++
++ if { [istarget *-*-linux*aout*] \
++ || [istarget *-*-linux*oldld*] } {
++ return 0
++ }
++
++ if { ![istarget *-*-netbsdelf*] \
++ && ([istarget *-*-netbsd*aout*] \
++ || [istarget *-*-netbsdpe*] \
++ || [istarget arm*-*-netbsd*] \
++ || [istarget sparc-*-netbsd*] \
++ || [istarget i*86-*-netbsd*] \
++ || [istarget m68*-*-netbsd*] \
++ || [istarget vax-*-netbsd*] \
++ || [istarget ns32k-*-netbsd*]) } {
++ return 0
++ }
++ return 1
++}
++
+
+ # run_dump_test FILE (optional:) EXTRA_OPTIONS
+ #
+--- gas/testsuite/gas/cfi/cfi-common-1.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-1.d 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,24 @@
++#readelf: -wf
++#name: CFI common 1
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: .*
++ Data alignment factor: .*
++ Return address column: .*
++ Augmentation data: 1b
++
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++
++00000014 00000018 00000018 FDE cie=00000000 pc=.*
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_def_cfa: r0 ofs 16
++ DW_CFA_offset: r1 at cfa-8
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_def_cfa_offset: 32
++ DW_CFA_offset: r2 at cfa-24
++
+--- gas/testsuite/gas/cfi/cfi-common-1.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-1.s 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,8 @@
++ .cfi_startproc simple
++ .long 0
++ .cfi_def_cfa 0, 16
++ .cfi_rel_offset 1, 8
++ .long 0
++ .cfi_adjust_cfa_offset 16
++ .cfi_rel_offset 2, 8
++ .cfi_endproc
+--- gas/testsuite/gas/cfi/cfi-common-2.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-2.d 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,29 @@
++#readelf: -wf
++#name: CFI common 2
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: .*
++ Data alignment factor: .*
++ Return address column: .*
++ Augmentation data: 1b
++
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++
++00000014 0000001c 00000018 FDE cie=00000000 pc=.*
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_def_cfa: r0 ofs 16
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_remember_state
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_def_cfa_offset: 0
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_restore_state
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_def_cfa_offset: 0
++ DW_CFA_nop
++
+--- gas/testsuite/gas/cfi/cfi-common-2.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-2.s 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,12 @@
++ .cfi_startproc simple
++ .long 0
++ .cfi_def_cfa 0, 16
++ .long 0
++ .cfi_remember_state
++ .long 0
++ .cfi_adjust_cfa_offset -16
++ .long 0
++ .cfi_restore_state
++ .long 0
++ .cfi_adjust_cfa_offset -16
++ .cfi_endproc
+--- gas/testsuite/gas/cfi/cfi-common-3.d 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-3.d 2003-06-11 19:16:58.000000000 -0400
+@@ -0,0 +1,21 @@
++#readelf: -wf
++#name: CFI common 2
++The section .eh_frame contains:
++
++00000000 00000010 00000000 CIE
++ Version: 1
++ Augmentation: "zR"
++ Code alignment factor: .*
++ Data alignment factor: .*
++ Return address column: .*
++ Augmentation data: 1b
++
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++
++00000014 00000010 00000018 FDE cie=00000000 pc=.*
++ DW_CFA_advance_loc: 4 to .*
++ DW_CFA_remember_state
++ DW_CFA_restore_state
++
+--- gas/testsuite/gas/cfi/cfi-common-3.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-common-3.s 2003-06-11 19:16:58.000000000 -0400
+@@ -0,0 +1,4 @@
++ .cfi_startproc simple
++ .long 0
++ .cfi_escape 10, 11
++ .cfi_endproc
+--- gas/testsuite/gas/cfi/cfi-diag-1.l 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-diag-1.l 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,2 @@
++.*: Assembler messages:
++.*:2: Error: register save offset not a multiple of .*
+--- gas/testsuite/gas/cfi/cfi-diag-1.s 2003-01-30 05:24:37.000000000 -0500
++++ gas/testsuite/gas/cfi/cfi-diag-1.s 2003-06-07 23:59:44.000000000 -0400
+@@ -0,0 +1,3 @@
++ .cfi_startproc
++ .cfi_offset 0, 1
++ .cfi_endproc
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi4.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi4.patch
new file mode 100644
index 000000000000..153703986c87
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-cfi4.patch
@@ -0,0 +1,384 @@
+2003-06-18 Jakub Jelinek <jakub@redhat.com>
+
+ * dw2gencfi.c (EH_FRAME_ALIGNMENT): Define if not defined.
+ (output_cie): Don't pad.
+ (output_fde): Add align argument. Pad to align if not 0.
+ (cfi_finish): Set .eh_frame alignment to EH_FRAME_ALIGNMENT.
+ Pad just last FDE to EH_FRAME_ALIGNMENT.
+
+ * gas/cfi/cfi-i386.d: Regenerated.
+ * gas/cfi/cfi-common-1.d: Regenerated.
+ * gas/cfi/cfi-common-2.d: Regenerated.
+ * gas/cfi/cfi-common-3.d: Regenerated.
+ * gas/cfi/cfi-x86_64.d: Regenerated.
+ * gas/cfi/cfi-alpha-1.d: Regenerated.
+ * gas/cfi/cfi-alpha-2.d: Regenerated.
+ * gas/cfi/cfi-alpha-3.d: Regenerated.
+
+--- gas/dw2gencfi.c.jj 2003-06-17 03:59:16.000000000 -0400
++++ gas/dw2gencfi.c 2003-06-18 07:25:06.000000000 -0400
+@@ -41,6 +41,14 @@
+ # endif
+ #endif
+
++#ifndef EH_FRAME_ALIGNMENT
++# ifdef BFD_ASSEMBLER
++# define EH_FRAME_ALIGNMENT (bfd_get_arch_size (stdoutput) == 64 ? 3 : 2)
++# else
++# define EH_FRAME_ALIGNMENT 2
++# endif
++#endif
++
+ #ifndef tc_cfi_frame_initial_instructions
+ # define tc_cfi_frame_initial_instructions() ((void)0)
+ #endif
+@@ -836,13 +844,12 @@ output_cie (struct cie_entry *cie)
+ for (i = cie->first; i != cie->last; i = i->next)
+ output_cfi_insn (i);
+
+- frag_align (2, 0, 0);
+ symbol_set_value_now (end_address);
+ }
+
+ static void
+ output_fde (struct fde_entry *fde, struct cie_entry *cie,
+- struct cfi_insn_data *first)
++ struct cfi_insn_data *first, int align)
+ {
+ symbolS *after_size_address, *end_address;
+ expressionS exp;
+@@ -874,7 +881,8 @@ output_fde (struct fde_entry *fde, struc
+ for (; first; first = first->next)
+ output_cfi_insn (first);
+
+- frag_align (2, 0, 0);
++ if (align)
++ frag_align (align, 0, 0);
+ symbol_set_value_now (end_address);
+ }
+
+@@ -990,7 +998,7 @@ cfi_finish (void)
+ SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY);
+ #endif
+ subseg_set (cfi_seg, 0);
+- record_alignment (cfi_seg, 2);
++ record_alignment (cfi_seg, EH_FRAME_ALIGNMENT);
+
+ /* Make sure check_eh_frame doesn't do anything with our output. */
+ save_flag_traditional_format = flag_traditional_format;
+@@ -1002,7 +1010,7 @@ cfi_finish (void)
+ struct cie_entry *cie;
+
+ cie = select_cie_for_fde (fde, &first);
+- output_fde (fde, cie, first);
++ output_fde (fde, cie, first, fde->next == NULL ? EH_FRAME_ALIGNMENT : 0);
+ }
+
+ flag_traditional_format = save_flag_traditional_format;
+--- gas/testsuite/gas/cfi/cfi-i386.d.jj 2003-05-28 02:56:00.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-i386.d 2003-06-18 12:04:17.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI on i386
+ The section .eh_frame contains:
+
+-00000000 00000014 00000000 CIE
++00000000 00000012 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+@@ -12,37 +12,29 @@ The section .eh_frame contains:
+
+ DW_CFA_def_cfa: r4 ofs 4
+ DW_CFA_offset: r8 at cfa-4
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000018 00000014 0000001c FDE cie=00000000 pc=00000020..00000032
+- DW_CFA_advance_loc: 6 to 00000026
++00000016 00000014 0000001a FDE cie=00000000 pc=0000001e..00000030
++ DW_CFA_advance_loc: 6 to 00000024
+ DW_CFA_def_cfa_offset: 4664
+- DW_CFA_advance_loc: 11 to 00000031
++ DW_CFA_advance_loc: 11 to 0000002f
+ DW_CFA_def_cfa_offset: 4
+
+-00000030 00000018 00000034 FDE cie=00000000 pc=0000004a..00000057
+- DW_CFA_advance_loc: 1 to 0000004b
++0000002e 00000018 00000032 FDE cie=00000000 pc=00000048..00000055
++ DW_CFA_advance_loc: 1 to 00000049
+ DW_CFA_def_cfa_offset: 8
+ DW_CFA_offset: r5 at cfa-8
+- DW_CFA_advance_loc: 2 to 0000004d
++ DW_CFA_advance_loc: 2 to 0000004b
+ DW_CFA_def_cfa_reg: r5
+- DW_CFA_advance_loc: 9 to 00000056
++ DW_CFA_advance_loc: 9 to 00000054
+ DW_CFA_def_cfa_reg: r4
+
+-0000004c 00000014 00000050 FDE cie=00000000 pc=00000073..00000083
+- DW_CFA_advance_loc: 2 to 00000075
++0000004a 00000014 0000004e FDE cie=00000000 pc=00000071..00000081
++ DW_CFA_advance_loc: 2 to 00000073
+ DW_CFA_def_cfa_reg: r3
+- DW_CFA_advance_loc: 13 to 00000082
++ DW_CFA_advance_loc: 13 to 00000080
+ DW_CFA_def_cfa: r4 ofs 4
+
+-00000064 00000010 00000068 FDE cie=00000000 pc=0000009b..000000a1
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+-
+-00000078 00000010 0000007c FDE cie=00000000 pc=000000b5..000000c4
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
++00000062 0000000d 00000066 FDE cie=00000000 pc=00000099..0000009f
++
++00000073 0000000d 00000077 FDE cie=00000000 pc=000000b0..000000bf
+
+--- gas/testsuite/gas/cfi/cfi-common-1.d.jj 2003-06-07 23:59:44.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-common-1.d 2003-06-18 12:13:51.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI common 1
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 0000000d 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: .*
+@@ -10,15 +10,14 @@ The section .eh_frame contains:
+ Return address column: .*
+ Augmentation data: 1b
+
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000014 00000018 00000018 FDE cie=00000000 pc=.*
++00000011 0000001b 00000015 FDE cie=00000000 pc=.*
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_def_cfa: r0 ofs 16
+ DW_CFA_offset: r1 at cfa-8
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_def_cfa_offset: 32
+ DW_CFA_offset: r2 at cfa-24
+-
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
+--- gas/testsuite/gas/cfi/cfi-common-2.d.jj 2003-06-07 23:59:44.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-common-2.d 2003-06-18 12:16:12.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI common 2
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 0000000d 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: .*
+@@ -10,11 +10,8 @@ The section .eh_frame contains:
+ Return address column: .*
+ Augmentation data: 1b
+
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000014 0000001c 00000018 FDE cie=00000000 pc=.*
++00000011 0000001[bf] 00000015 FDE cie=00000000 pc=.*
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_def_cfa: r0 ofs 16
+ DW_CFA_advance_loc: 4 to .*
+@@ -25,5 +22,5 @@ The section .eh_frame contains:
+ DW_CFA_restore_state
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_def_cfa_offset: 0
+- DW_CFA_nop
+-
++# 64-bit arches will have here 4 times DW_CFA_nop
++#...
+--- gas/testsuite/gas/cfi/cfi-x86_64.d.jj 2003-05-28 02:56:00.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-x86_64.d 2003-06-18 12:30:09.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI on x86-64
+ The section .eh_frame contains:
+
+-00000000 00000014 00000000 CIE
++00000000 00000012 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 1
+@@ -12,40 +12,32 @@ The section .eh_frame contains:
+
+ DW_CFA_def_cfa: r7 ofs 8
+ DW_CFA_offset: r16 at cfa-8
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000018 00000014 0000001c FDE cie=00000000 pc=00000020..00000034
+- DW_CFA_advance_loc: 7 to 00000027
++00000016 00000014 0000001a FDE cie=00000000 pc=0000001e..00000032
++ DW_CFA_advance_loc: 7 to 00000025
+ DW_CFA_def_cfa_offset: 4668
+- DW_CFA_advance_loc: 12 to 00000033
++ DW_CFA_advance_loc: 12 to 00000031
+ DW_CFA_def_cfa_offset: 8
+
+-00000030 0000001c 00000034 FDE cie=00000000 pc=00000038..00000047
+- DW_CFA_advance_loc: 1 to 00000039
++0000002e 00000019 00000032 FDE cie=00000000 pc=00000036..00000045
++ DW_CFA_advance_loc: 1 to 00000037
+ DW_CFA_def_cfa_offset: 16
+ DW_CFA_offset: r6 at cfa-16
+- DW_CFA_advance_loc: 3 to 0000003c
++ DW_CFA_advance_loc: 3 to 0000003a
+ DW_CFA_def_cfa_reg: r6
+- DW_CFA_advance_loc: 10 to 00000046
++ DW_CFA_advance_loc: 10 to 00000044
+ DW_CFA_def_cfa: r7 ofs 8
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000050 00000014 00000054 FDE cie=00000000 pc=00000058..0000006b
+- DW_CFA_advance_loc: 3 to 0000005b
++0000004b 00000013 0000004f FDE cie=00000000 pc=00000053..00000066
++ DW_CFA_advance_loc: 3 to 00000056
+ DW_CFA_def_cfa_reg: r12
+- DW_CFA_advance_loc: 15 to 0000006a
++ DW_CFA_advance_loc: 15 to 00000065
+ DW_CFA_def_cfa_reg: r7
+- DW_CFA_nop
+
+-00000068 00000010 0000006c FDE cie=00000000 pc=00000070..00000076
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
++00000062 0000000d 00000066 FDE cie=00000000 pc=0000006a..00000070
+
+-0000007c 00000010 00000080 FDE cie=00000000 pc=00000084..00000096
++00000073 00000011 00000077 FDE cie=00000000 pc=0000007b..0000008d
++ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+ DW_CFA_nop
+--- gas/testsuite/gas/cfi/cfi-common-3.d.jj 2003-06-11 19:16:58.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-common-3.d 2003-06-18 12:18:06.000000000 -0400
+@@ -1,8 +1,8 @@
+ #readelf: -wf
+-#name: CFI common 2
++#name: CFI common 3
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 0000000d 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: .*
+@@ -10,12 +10,11 @@ The section .eh_frame contains:
+ Return address column: .*
+ Augmentation data: 1b
+
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+-00000014 00000010 00000018 FDE cie=00000000 pc=.*
++00000011 00000013 00000015 FDE cie=00000000 pc=.*
+ DW_CFA_advance_loc: 4 to .*
+ DW_CFA_remember_state
+ DW_CFA_restore_state
+-
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
+--- gas/testsuite/gas/cfi/cfi-alpha-1.d.jj 2003-05-29 23:01:12.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-alpha-1.d 2003-06-18 12:38:36.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI on alpha
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 0000000f 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 4
+@@ -11,16 +11,12 @@ The section .eh_frame contains:
+ Augmentation data: 1b
+
+ DW_CFA_def_cfa_reg: r30
+- DW_CFA_nop
+
+-00000014 0000001c 00000018 FDE cie=00000000 pc=0000001c..00000050
+- DW_CFA_advance_loc: 24 to 00000034
++00000013 00000019 00000017 FDE cie=00000000 pc=0000001b..0000004f
++ DW_CFA_advance_loc: 24 to 00000033
+ DW_CFA_def_cfa: r15 ofs 32
+ DW_CFA_offset: r26 at cfa-32
+ DW_CFA_offset: r9 at cfa-24
+ DW_CFA_offset: r15 at cfa-16
+ DW_CFA_offset: r34 at cfa-8
+- DW_CFA_nop
+- DW_CFA_nop
+- DW_CFA_nop
+
+--- gas/testsuite/gas/cfi/cfi-alpha-2.d.jj 2003-05-31 15:36:45.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-alpha-2.d 2003-06-18 12:41:56.000000000 -0400
+@@ -5,5 +5,5 @@
+
+ RELOCATION RECORDS FOR \[\.eh_frame\]:
+ OFFSET TYPE VALUE
+-0*000001c SREL32 \.text
+-0*0000030 SREL32 \.text\+0x0*0000004
++0*000001b SREL32 \.text
++0*000002c SREL32 \.text\+0x0*0000004
+--- gas/testsuite/gas/cfi/cfi-alpha-3.d.jj 2003-06-04 23:27:03.000000000 -0400
++++ gas/testsuite/gas/cfi/cfi-alpha-3.d 2003-06-18 12:42:52.000000000 -0400
+@@ -2,7 +2,7 @@
+ #name: CFI on alpha, 3
+ The section .eh_frame contains:
+
+-00000000 00000010 00000000 CIE
++00000000 0000000f 00000000 CIE
+ Version: 1
+ Augmentation: "zR"
+ Code alignment factor: 4
+@@ -11,22 +11,26 @@ The section .eh_frame contains:
+ Augmentation data: 1b
+
+ DW_CFA_def_cfa_reg: r30
+- DW_CFA_nop
+
+-00000014 00000024 00000018 FDE cie=00000000 pc=0000001c..0000005c
+- DW_CFA_advance_loc: 4 to 00000020
++00000013 00000029 00000017 FDE cie=00000000 pc=0000001b..0000005b
++ DW_CFA_advance_loc: 4 to 0000001f
+ DW_CFA_def_cfa_offset: 32
+- DW_CFA_advance_loc: 4 to 00000024
++ DW_CFA_advance_loc: 4 to 00000023
+ DW_CFA_offset: r26 at cfa-32
+- DW_CFA_advance_loc: 4 to 00000028
++ DW_CFA_advance_loc: 4 to 00000027
+ DW_CFA_offset: r9 at cfa-24
+- DW_CFA_advance_loc: 4 to 0000002c
++ DW_CFA_advance_loc: 4 to 0000002b
+ DW_CFA_offset: r15 at cfa-16
+- DW_CFA_advance_loc: 4 to 00000030
++ DW_CFA_advance_loc: 4 to 0000002f
+ DW_CFA_offset: r34 at cfa-8
+- DW_CFA_advance_loc: 4 to 00000034
++ DW_CFA_advance_loc: 4 to 00000033
+ DW_CFA_def_cfa_reg: r15
+- DW_CFA_advance_loc: 36 to 00000058
++ DW_CFA_advance_loc: 36 to 00000057
+ DW_CFA_def_cfa: r30 ofs 0
+ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
++ DW_CFA_nop
+
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-eh-frame-ro.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-eh-frame-ro.patch
new file mode 100644
index 000000000000..83b947df1b06
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-eh-frame-ro.patch
@@ -0,0 +1,475 @@
+2002-11-22 Jakub Jelinek <jakub@redhat.com>
+
+ * ldgram.y (sect_constraint): New.
+ (ONLY_IF_RO, ONLY_IF_RW): New tokens.
+ (section): Add sect_constraint. Pass additional argument
+ to lang_enter_output_section_statement.
+ * mri.c (mri_draw_tree): Pass additional argument to
+ lang_enter_output_section_statement.
+ * emultempl/pe.em (place_orphan): Likewise.
+ (output_prev_sec_find): Disregard output section statements with
+ constraint == -1.
+ * emultempl/mmo.em (output_prev_sec_find): Likewise.
+ (mmo_place_orphan): Pass additional argument to
+ lang_enter_output_section_statement.
+ * emultempl/elf32.em (output_prev_sec_find): Disregard output section
+ statements with constraint == -1.
+ (place_orphan): Pass additional argument to
+ lang_enter_output_section_statement.
+ * ldlang.c (lang_enter_overlay_section): Likewise.
+ (lang_output_section_find_1): New.
+ (lang_output_section_find): Use it.
+ (lang_output_section_statement_lookup_1): New.
+ (lang_output_section_statement_lookup): Use it.
+ (check_section_callback, check_input_sections): New.
+ (map_input_to_output_sections): Check if all input sections
+ are readonly if ONLY_IF_RO or ONLY_IF_RW was seen.
+ (strip_excluded_output_sections): Disregard output section statements
+ with constraint == -1.
+ (lang_record_phdrs): Likewise.
+ (lang_enter_output_section_statement): Add constraint argument.
+ Use lang_output_section_statement_lookup_1.
+ * ldlang.h (lang_output_section_statement_type): Add constraint
+ and all_input_readonly fields.
+ (lang_enter_output_section_statement): Adjust prototype.
+ * ldlex.l (ONLY_IF_RO, ONLY_IF_RW): New tokens.
+ * scripttempl/elf.sc (.eh_frame, .gcc_except_table): Move into text
+ segment if all input sections are readonly.
+
+--- ld/emultempl/mmo.em.jj Mon Dec 16 15:22:53 2002
++++ ld/emultempl/mmo.em Mon May 19 06:31:40 2003
+@@ -56,6 +56,8 @@ output_prev_sec_find (os)
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
++ if (lookup->constraint == -1)
++ continue;
+ if (lookup == os)
+ break;
+ if (lookup->bfd_section != NULL
+@@ -141,7 +143,7 @@ mmo_place_orphan (file, s)
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- (etree_type *) NULL);
++ (etree_type *) NULL, 0);
+
+ lang_add_section (&os->children, s, os, file);
+
+--- ld/emultempl/pe.em.jj Mon May 5 17:46:50 2003
++++ ld/emultempl/pe.em Mon May 19 06:31:40 2003
+@@ -1511,6 +1511,8 @@ output_prev_sec_find (os)
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
++ if (lookup->constraint == -1)
++ continue;
+ if (lookup == os)
+ return s;
+
+@@ -1677,7 +1679,7 @@ gld_${EMULATION_NAME}_place_orphan (file
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- (etree_type *) NULL);
++ (etree_type *) NULL, 0);
+
+ lang_add_section (&add_child, s, os, file);
+
+--- ld/emultempl/elf32.em.jj Thu May 15 16:42:25 2003
++++ ld/emultempl/elf32.em Mon May 19 06:31:40 2003
+@@ -1056,7 +1056,8 @@ output_rel_find (sec)
+ for (u = lang_output_section_statement.head; u; u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+- if (strncmp (".rel", lookup->name, 4) == 0)
++ if (lookup->constraint != -1
++ && strncmp (".rel", lookup->name, 4) == 0)
+ {
+ /* Don't place after .rel.plt as doing so results in wrong
+ dynamic tags. Also, place allocated reloc sections before
+@@ -1296,7 +1297,7 @@ gld${EMULATION_NAME}_place_orphan (file,
+ (bfd_vma) 0,
+ (etree_type *) NULL,
+ (etree_type *) NULL,
+- load_base);
++ load_base, 0);
+
+ lang_add_section (&os->children, s, os, file);
+
+--- ld/scripttempl/elf.sc.jj Mon May 5 17:46:50 2003
++++ ld/scripttempl/elf.sc Mon May 19 06:31:40 2003
+@@ -280,6 +280,8 @@ cat <<EOF
+ ${CREATE_SHLIB-${SBSS2}}
+ ${OTHER_READONLY_SECTIONS}
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
++ .eh_frame ${RELOCATING-0} : ONLY_IF_RO { KEEP (*(.eh_frame)) }
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table) }
+
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+@@ -312,8 +314,8 @@ cat <<EOF
+ .data1 ${RELOCATING-0} : { *(.data1) }
+ .tdata ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
+ .tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
+- .eh_frame ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
+- .gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
++ .eh_frame ${RELOCATING-0} : ONLY_IF_RW { KEEP (*(.eh_frame)) }
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table) }
+ ${WRITABLE_RODATA+${RODATA}}
+ ${OTHER_READWRITE_SECTIONS}
+ ${TEXT_DYNAMIC-${DYNAMIC}}
+--- ld/ldgram.y.jj Mon May 5 17:46:49 2003
++++ ld/ldgram.y Mon May 19 06:34:38 2003
+@@ -143,14 +143,14 @@ static int error_index;
+ %token ORIGIN FILL
+ %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
+ %token ALIGNMOD AT PROVIDE
+-%type <token> assign_op atype attributes_opt
++%type <token> assign_op atype attributes_opt sect_constraint
+ %type <name> filename
+ %token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
+ %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
+ %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
+ %token <name> VERS_TAG VERS_IDENTIFIER
+ %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+-%token KEEP
++%token KEEP ONLY_IF_RO ONLY_IF_RW
+ %token EXCLUDE_FILE
+ %type <versyms> vers_defns
+ %type <versnode> vers_tag
+@@ -828,21 +828,28 @@ opt_at:
+ | { $$ = 0; }
+ ;
+
++sect_constraint:
++ ONLY_IF_RO { $$ = ONLY_IF_RO; }
++ | ONLY_IF_RW { $$ = ONLY_IF_RW; }
++ | { $$ = 0; }
++ ;
++
+ section: NAME { ldlex_expression(); }
+ opt_exp_with_type
+ opt_at { ldlex_popstate (); ldlex_script (); }
++ sect_constraint
+ '{'
+ {
+ lang_enter_output_section_statement($1, $3,
+ sectype,
+- 0, 0, 0, $4);
++ 0, 0, 0, $4, $6);
+ }
+ statement_list_opt
+ '}' { ldlex_popstate (); ldlex_expression (); }
+ memspec_opt memspec_at_opt phdr_opt fill_opt
+ {
+ ldlex_popstate ();
+- lang_leave_output_section_statement ($14, $11, $13, $12);
++ lang_leave_output_section_statement ($15, $12, $14, $13);
+ }
+ opt_comma
+ {}
+--- ld/mri.c.jj Tue Jan 21 13:21:34 2003
++++ ld/mri.c Mon May 19 06:31:40 2003
+@@ -237,7 +237,7 @@ mri_draw_tree ()
+ lang_enter_output_section_statement (p->name, base,
+ p->ok_to_load ? 0 : noload_section,
+ 1, align, subalign,
+- (etree_type *) NULL);
++ (etree_type *) NULL, 0);
+ base = 0;
+ tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
+ tmp->next = NULL;
+--- ld/ldlang.h.jj Wed Mar 19 12:19:16 2003
++++ ld/ldlang.h Mon May 19 06:31:40 2003
+@@ -132,6 +132,8 @@ typedef struct lang_output_section_state
+
+ int subsection_alignment; /* alignment of components */
+ int section_alignment; /* alignment of start of section */
++ int constraint;
++ bfd_boolean all_input_readonly;
+
+ union etree_union *load_base;
+
+@@ -394,7 +396,7 @@ extern lang_output_section_statement_typ
+ bfd_vma block_value,
+ etree_type *align,
+ etree_type *subalign,
+- etree_type *));
++ etree_type *, int));
+ extern void lang_final
+ PARAMS ((void));
+ extern void lang_process
+--- ld/ldlang.c.jj Thu May 15 16:42:25 2003
++++ ld/ldlang.c Mon May 19 06:31:40 2003
+@@ -72,6 +72,10 @@ static lang_input_statement_type *new_af
+ bfd_boolean));
+ static lang_memory_region_type *lang_memory_default
+ PARAMS ((asection *));
++static lang_output_section_statement_type * lang_output_section_find_1
++ PARAMS ((const char *, int));
++static lang_output_section_statement_type *
++ lang_output_section_statement_lookup_1 PARAMS ((const char *, int));
+ static void lang_map_flags
+ PARAMS ((flagword));
+ static void init_os
+@@ -94,6 +98,9 @@ static lang_statement_union_type *wild_s
+ static void output_section_callback
+ PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
+ lang_input_statement_type *, PTR));
++static void check_section_callback
++ PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
++ lang_input_statement_type *, PTR));
+ static lang_input_statement_type *lookup_name
+ PARAMS ((const char *));
+ static bfd_boolean load_symbols
+@@ -111,6 +118,9 @@ static void lang_reasonable_defaults
+ PARAMS ((void));
+ static void insert_undefined
+ PARAMS ((const char *));
++static void check_input_sections
++ PARAMS ((lang_statement_union_type *,
++ lang_output_section_statement_type *));
+ static void lang_place_undefineds
+ PARAMS ((void));
+ static void map_input_to_output_sections
+@@ -745,9 +755,10 @@ lang_memory_default (section)
+ return lang_memory_region_lookup ("*default*");
+ }
+
+-lang_output_section_statement_type *
+-lang_output_section_find (name)
++static lang_output_section_statement_type *
++lang_output_section_find_1 (name, constraint)
+ const char *const name;
++ int constraint;
+ {
+ lang_statement_union_type *u;
+ lang_output_section_statement_type *lookup;
+@@ -757,7 +768,9 @@ lang_output_section_find (name)
+ u = lookup->next)
+ {
+ lookup = &u->output_section_statement;
+- if (strcmp (name, lookup->name) == 0)
++ if (strcmp (name, lookup->name) == 0
++ && lookup->constraint != -1
++ && (constraint == 0 || constraint == lookup->constraint))
+ {
+ return lookup;
+ }
+@@ -766,12 +779,20 @@ lang_output_section_find (name)
+ }
+
+ lang_output_section_statement_type *
+-lang_output_section_statement_lookup (name)
++lang_output_section_find (name)
++ const char *const name;
++{
++ return lang_output_section_find_1 (name, 0);
++}
++
++static lang_output_section_statement_type *
++lang_output_section_statement_lookup_1 (name, constraint)
+ const char *const name;
++ int constraint;
+ {
+ lang_output_section_statement_type *lookup;
+
+- lookup = lang_output_section_find (name);
++ lookup = lang_output_section_find_1 (name, constraint);
+ if (lookup == (lang_output_section_statement_type *) NULL)
+ {
+
+@@ -786,6 +807,7 @@ lang_output_section_statement_lookup (na
+ lookup->next = (lang_statement_union_type *) NULL;
+ lookup->bfd_section = (asection *) NULL;
+ lookup->processed = FALSE;
++ lookup->constraint = constraint;
+ lookup->sectype = normal_section;
+ lookup->addr_tree = (etree_type *) NULL;
+ lang_list_init (&lookup->children);
+@@ -805,6 +827,13 @@ lang_output_section_statement_lookup (na
+ return lookup;
+ }
+
++lang_output_section_statement_type *
++lang_output_section_statement_lookup (name)
++ const char *const name;
++{
++ return lang_output_section_statement_lookup_1 (name, 0);
++}
++
+ static void
+ lang_map_flags (flag)
+ flagword flag;
+@@ -1482,6 +1511,31 @@ output_section_callback (ptr, sec, secti
+ }
+ }
+
++/* Check if all sections in a wild statement for a particular FILE
++ are readonly. */
++
++static void
++check_section_callback (ptr, sec, section, file, output)
++ lang_wild_statement_type *ptr ATTRIBUTE_UNUSED;
++ struct wildcard_list *sec ATTRIBUTE_UNUSED;
++ asection *section;
++ lang_input_statement_type *file ATTRIBUTE_UNUSED;
++ PTR output;
++{
++ /* Exclude sections that match UNIQUE_SECTION_LIST. */
++ if (unique_section_p (bfd_get_section_name (file->the_bfd, section)))
++ return;
++
++ if (section->output_section == NULL)
++ {
++ flagword flags = bfd_get_section_flags (section->owner, section);
++
++ if ((flags & SEC_READONLY) == 0)
++ ((lang_output_section_statement_type *) output)->all_input_readonly
++ = FALSE;
++ }
++}
++
+ /* This is passed a file name which must have been seen already and
+ added to the statement tree. We will see if it has been opened
+ already and had its symbols read. If not then we'll read it. */
+@@ -2151,6 +2205,41 @@ lang_place_undefineds ()
+ }
+ }
+
++/* Check for all readonly or some readwrite sections. */
++
++static void
++check_input_sections (s, output_section_statement)
++ lang_statement_union_type *s;
++ lang_output_section_statement_type *output_section_statement;
++{
++ for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
++ {
++ switch (s->header.type)
++ {
++ case lang_wild_statement_enum:
++ walk_wild (&s->wild_statement, check_section_callback,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ case lang_constructors_statement_enum:
++ check_input_sections (constructor_list.head,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ case lang_group_statement_enum:
++ check_input_sections (s->group_statement.children.head,
++ output_section_statement);
++ if (! output_section_statement->all_input_readonly)
++ return;
++ break;
++ default:
++ break;
++ }
++ }
++}
++
+ /* Open input files and attach to output sections. */
+
+ static void
+@@ -2172,6 +2261,23 @@ map_input_to_output_sections (s, target,
+ output_section_statement);
+ break;
+ case lang_output_section_statement_enum:
++ if (s->output_section_statement.constraint)
++ {
++ if (s->output_section_statement.constraint == -1)
++ break;
++ s->output_section_statement.all_input_readonly = TRUE;
++ check_input_sections (s->output_section_statement.children.head,
++ &s->output_section_statement);
++ if ((s->output_section_statement.all_input_readonly
++ && s->output_section_statement.constraint == ONLY_IF_RW)
++ || (!s->output_section_statement.all_input_readonly
++ && s->output_section_statement.constraint == ONLY_IF_RO))
++ {
++ s->output_section_statement.constraint = -1;
++ break;
++ }
++ }
++
+ map_input_to_output_sections (s->output_section_statement.children.head,
+ target,
+ &s->output_section_statement);
+@@ -2242,6 +2348,8 @@ strip_excluded_output_sections ()
+ asection *s;
+
+ os = &u->output_section_statement;
++ if (os->constraint == -1)
++ continue;
+ s = os->bfd_section;
+ if (s != NULL && (s->flags & SEC_EXCLUDE) != 0)
+ {
+@@ -4132,7 +4240,7 @@ topower (x)
+ lang_output_section_statement_type *
+ lang_enter_output_section_statement (output_section_statement_name,
+ address_exp, sectype, block_value,
+- align, subalign, ebase)
++ align, subalign, ebase, constraint)
+ const char *output_section_statement_name;
+ etree_type *address_exp;
+ enum section_type sectype;
+@@ -4140,12 +4248,14 @@ lang_enter_output_section_statement (out
+ etree_type *align;
+ etree_type *subalign;
+ etree_type *ebase;
++ int constraint;
+ {
+ lang_output_section_statement_type *os;
+
+ current_section =
+ os =
+- lang_output_section_statement_lookup (output_section_statement_name);
++ lang_output_section_statement_lookup_1 (output_section_statement_name,
++ constraint);
+
+ /* Add this statement to tree. */
+ #if 0
+@@ -4879,6 +4989,8 @@ lang_record_phdrs ()
+ struct lang_output_section_phdr_list *pl;
+
+ os = &u->output_section_statement;
++ if (os->constraint == -1)
++ continue;
+
+ pl = os->phdrs;
+ if (pl != NULL)
+@@ -4939,7 +5051,8 @@ lang_record_phdrs ()
+ {
+ struct lang_output_section_phdr_list *pl;
+
+- if (u->output_section_statement.bfd_section == NULL)
++ if (u->output_section_statement.constraint == -1
++ || u->output_section_statement.bfd_section == NULL)
+ continue;
+
+ for (pl = u->output_section_statement.phdrs;
+@@ -5009,7 +5122,7 @@ lang_enter_overlay_section (name)
+ etree_type *size;
+
+ lang_enter_output_section_statement (name, overlay_vma, normal_section,
+- 0, 0, 0, 0);
++ 0, 0, 0, 0, 0);
+
+ /* If this is the first section, then base the VMA of future
+ sections on this one. This will work correctly even if `.' is
+--- ld/ldlex.l.jj Mon May 5 17:46:49 2003
++++ ld/ldlex.l Mon May 19 06:31:40 2003
+@@ -303,6 +303,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^]([*?
+ <EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);}
+ <EXPRESSION,BOTH,SCRIPT>"INFO" { RTOKEN(INFO);}
+ <EXPRESSION,BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY);}
++<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); }
++<EXPRESSION,BOTH,SCRIPT>"ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); }
+ <BOTH,SCRIPT>"o" { RTOKEN(ORIGIN);}
+ <BOTH,SCRIPT>"org" { RTOKEN(ORIGIN);}
+ <BOTH,SCRIPT>"l" { RTOKEN( LENGTH);}
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-execstack.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-execstack.patch
new file mode 100644
index 000000000000..9b04bb119d5b
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-execstack.patch
@@ -0,0 +1,92 @@
+2003-06-04 Jakub Jelinek <jakub@redhat.com>
+
+ * as.c (show_usage): Document --execstack and --noexecstack.
+ (parse_args): Add --execstack and --noexecstack.
+ (main): Create .note.GNU-stack section if --execstack or
+ --noexecstack was given on comand line, set its SHF_EXECINSTR bit.
+ * as.h (flag_execstack, flag_noexecstack): New.
+
+--- gas/as.c.jj 2003-05-30 09:44:26.000000000 -0400
++++ gas/as.c 2003-06-04 07:43:05.000000000 -0400
+@@ -268,6 +268,12 @@ Options:\n\
+ emulate output (default %s)\n"), def_em);
+ }
+ #endif
++#if defined BFD_ASSEMBLER && (defined OBJ_ELF || defined OBJ_MAYBE_ELF)
++ fprintf (stream, _("\
++ --execstack require executable stack for this object\n"));
++ fprintf (stream, _("\
++ --noexecstack don't require executable stack for this object\n"));
++#endif
+ fprintf (stream, _("\
+ -f skip whitespace and comment preprocessing\n"));
+ fprintf (stream, _("\
+@@ -437,7 +443,13 @@ parse_args (pargc, pargv)
+ {"warn", no_argument, NULL, OPTION_WARN},
+ #define OPTION_TARGET_HELP (OPTION_STD_BASE + 19)
+ {"target-help", no_argument, NULL, OPTION_TARGET_HELP},
+-#define OPTION_WARN_FATAL (OPTION_STD_BASE + 20)
++#if defined BFD_ASSEMBLER && (defined OBJ_ELF || defined OBJ_MAYBE_ELF)
++#define OPTION_EXECSTACK (OPTION_STD_BASE + 20)
++ {"execstack", no_argument, NULL, OPTION_EXECSTACK},
++#define OPTION_NOEXECSTACK (OPTION_STD_BASE + 21)
++ {"noexecstack", no_argument, NULL, OPTION_NOEXECSTACK},
++#endif
++#define OPTION_WARN_FATAL (OPTION_STD_BASE + 22)
+ {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL}
+ /* When you add options here, check that they do not collide with
+ OPTION_MD_BASE. See as.h. */
+@@ -698,6 +710,18 @@ the GNU General Public License. This pr
+ flag_fatal_warnings = 1;
+ break;
+
++#if defined BFD_ASSEMBLER && (defined OBJ_ELF || defined OBJ_MAYBE_ELF)
++ case OPTION_EXECSTACK:
++ flag_execstack = 1;
++ flag_noexecstack = 0;
++ break;
++
++ case OPTION_NOEXECSTACK:
++ flag_noexecstack = 1;
++ flag_execstack = 0;
++ break;
++#endif
++
+ case 'Z':
+ flag_always_generate_output = 1;
+ break;
+@@ -907,6 +931,19 @@ main (argc, argv)
+ md_end ();
+ #endif
+
++#if defined BFD_ASSEMBLER && (defined OBJ_ELF || defined OBJ_MAYBE_ELF)
++ if ((flag_execstack || flag_noexecstack)
++ && OUTPUT_FLAVOR == bfd_target_elf_flavour)
++ {
++ segT gnustack;
++
++ gnustack = subseg_new (".note.GNU-stack", 0);
++ bfd_set_section_flags (stdoutput, gnustack,
++ SEC_READONLY | (flag_execstack ? SEC_CODE : 0));
++
++ }
++#endif
++
+ /* If we've been collecting dwarf2 .debug_line info, either for
+ assembly debugging or on behalf of the compiler, emit it now. */
+ dwarf2_finish ();
+--- gas/as.h.jj 2003-05-23 09:24:40.000000000 -0400
++++ gas/as.h 2003-06-04 05:17:39.000000000 -0400
+@@ -436,6 +436,12 @@ COMMON int flag_strip_local_absolute;
+ /* True if we should generate a traditional format object file. */
+ COMMON int flag_traditional_format;
+
++/* TRUE if .note.GNU-stack section with SEC_CODE should be created */
++COMMON int flag_execstack;
++
++/* TRUE if .note.GNU-stack section with SEC_CODE should be created */
++COMMON int flag_noexecstack;
++
+ /* name of emitted object file */
+ COMMON char *out_file_name;
+
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-pred.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-pred.patch
new file mode 100644
index 000000000000..52097d66210a
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-gas-pred.patch
@@ -0,0 +1,46 @@
+2003-06-06 H.J. Lu <hongjiu.lu@intel.com>
+
+ * app.c (do_scrub_chars): Add states 14 and 15 to handle
+ predicate for ia64.
+
+--- gas/app.c.pred 2003-04-24 14:19:07.000000000 -0700
++++ gas/app.c 2003-06-07 07:48:33.000000000 -0700
+@@ -374,6 +374,12 @@ do_scrub_chars (get, tostart, tolen)
+ 13: After seeing a vertical bar, looking for a second
+ vertical bar as a parallel expression separator.
+ #endif
++#ifdef TC_IA64
++ 14: After seeing a `(' at state 0, looking for a `)' as
++ predicate.
++ 15: After seeing a `(' at state 1, looking for a `)' as
++ predicate.
++#endif
+ */
+
+ /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+@@ -674,6 +680,25 @@ do_scrub_chars (get, tostart, tolen)
+ /* flushchar: */
+ ch = GET ();
+
++#ifdef TC_IA64
++ if (ch == '(' && (state == 0 || state == 1))
++ {
++ state += 14;
++ PUT (ch);
++ continue;
++ }
++ else if (state == 14 || state == 15)
++ {
++ if (ch == ')')
++ state -= 14;
++ else
++ {
++ PUT (ch);
++ continue;
++ }
++ }
++#endif
++
+ recycle:
+
+ #if defined TC_ARM && defined OBJ_ELF
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ltconfig-multilib.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ltconfig-multilib.patch
new file mode 100644
index 000000000000..26dfb8492c3c
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ltconfig-multilib.patch
@@ -0,0 +1,26 @@
+--- ltconfig.jj 2003-02-03 16:56:49.000000000 +0900
++++ ltconfig 2003-02-03 16:56:49.000000000 +0900
+@@ -1237,6 +1237,23 @@
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
++
++ # Find out which ABI we are using (multilib hack).
++ case "$host_cpu" in
++ x86_64*|s390*|sparc*|ppc*|powerpc*)
++ echo "$progname:@lineno@: checking multilib ABI type" 1>&5
++ touch conftest.$ac_ext
++ if { (eval echo $progname: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
++ case `/usr/bin/file conftest.o` in
++ *64-bit*)
++ sys_lib_dlsearch_path_spec="/lib64 /usr/lib64"
++ sys_lib_search_path_spec="/lib64 /usr/lib64 /usr/local/lib64"
++ ;;
++ esac
++ fi
++ rm -rf conftest*
++ ;;
++ esac
+ ;;
+
+ netbsd*)
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie.patch
new file mode 100644
index 000000000000..5d1cf56a4bc6
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie.patch
@@ -0,0 +1,632 @@
+2003-05-29 Ulrich Drepper <drepper@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+bfd/
+ * elflink.h (elf_link_add_object_symbols): Use !info->executable
+ instead of info->shared where appropriate.
+ (bfd_elfNN_size_dynamic_sections, elf_link_output_extsym): Likewise.
+ * elflink.c (_bfd_elf_create_got_section): Likewise.
+ (_bfd_elf_link_create_dynamic_sections): Likewise.
+ (_bfd_elf_link_assign_sym_version): Likewise.
+ * elf32-i386.c (elf_i386_size_dynamic_sections): Create .interp section
+ and DT_DEBUG dynamic tag even for position independent executables.
+ * elf32-ppc.c (ppc_elf_size_dynamic_sections): Likewise.
+ * elf32-s390.c (elf_s390_size_dynamic_sections: Likewise.
+ * elf64-ppc.c (ppc64_elf_size_dynamic_sections: Likewise.
+ * elf64-s390.c (elf_s390_size_dynamic_sections: Likewise.
+ * elf64-x86-64.c (elf64_x86_64_size_dynamic_sections: Likewise.
+ * elfxx-ia64.c (elfNN_ia64_size_dynamic_sections: Likewise.
+ * elf32-sparc.c (elf32_sparc_size_dynamic_sections: Likewise.
+ * elf64-alpha.c (elf64_alpha_size_dynamic_sections: Likewise.
+ * elf64-sparc.c (sparc64_elf_size_dynamic_sections: Likewise.
+include/
+ * bfdlink.h (struct bfd_link_info): Add pie and executable
+ bits.
+ld/
+ * lexsup.c (OPTION_PIE): Define.
+ (ld_options): Add -pie and --pic-executable options.
+ (parse_args): Handle OPTION_PIE.
+ * ldmain.c (main): Initialize link_info.pie and
+ link_info.executable.
+ * genscripts.sh: Generate PIE scripts.
+ * ld.texinfo: Document -pie and --pic-executable options.
+ * emultempl/elf32.em (gld${EMULATION_NAME}_after_open):
+ (gld${EMULATION_NAME}_place_orphan): Likewise.
+ (gld${EMULATION_NAME}_get_script): Include PIE scripts.
+ * scripttempl/elf.sc: In PIE scripts set . the same way as in
+ shared scripts.
+ * emulparams/elf_i386.sh (GENERATE_PIE_SCRIPT): Set to yes.
+ * emulparams/elf64_ia64.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf32ppc.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf64ppc.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf_x86_64.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf_s390.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf32_sparc.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf64_sparc.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf64alpha.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf64_s390.sh (GENERATE_PIE_SCRIPT): Likewise.
+ * emulparams/elf_i386.sh (GENERATE_PIE_SCRIPT): Likewise.
+
+--- bfd/elf32-i386.c.jj 2003-05-23 10:18:52.000000000 -0400
++++ bfd/elf32-i386.c 2003-05-28 03:18:13.000000000 -0400
+@@ -1797,7 +1797,7 @@ elf_i386_size_dynamic_sections (output_b
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ if (s == NULL)
+@@ -1963,7 +1963,7 @@ elf_i386_size_dynamic_sections (output_b
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (! info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elflink.h.jj 2003-05-23 10:18:52.000000000 -0400
++++ bfd/elflink.h 2003-05-28 06:27:38.000000000 -0400
+@@ -474,7 +474,7 @@ elf_link_add_object_symbols (abfd, info)
+ .gnu.warning.SYMBOL are treated as warning symbols for the given
+ symbol. This differs from .gnu.warning sections, which generate
+ warnings when they are included in an output file. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ asection *s;
+
+@@ -1321,7 +1321,7 @@ elf_link_add_object_symbols (abfd, info)
+ }
+ else
+ new_flag = ELF_LINK_HASH_DEF_REGULAR;
+- if (info->shared
++ if (! info->executable
+ || (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_REF_DYNAMIC)) != 0)
+ dynsym = TRUE;
+@@ -2174,7 +2174,7 @@ NAME(bfd_elf,size_dynamic_sections) (out
+ if (bfd_get_section_by_name (output_bfd, ".preinit_array") != NULL)
+ {
+ /* DT_PREINIT_ARRAY is not allowed in shared library. */
+- if (info->shared)
++ if (! info->executable)
+ {
+ bfd *sub;
+ asection *o;
+@@ -2440,7 +2440,7 @@ NAME(bfd_elf,size_dynamic_sections) (out
+
+ if (info->flags_1)
+ {
+- if (! info->shared)
++ if (info->executable)
+ info->flags_1 &= ~ (DF_1_INITFIRST
+ | DF_1_NODELETE
+ | DF_1_NOOPEN);
+@@ -4417,7 +4417,8 @@ elf_link_output_extsym (h, data)
+ referenced by regular files, because we will already have issued
+ warnings for them. */
+ if (! finfo->info->relocateable
+- && (! finfo->info->shared || ! finfo->info->allow_shlib_undefined)
++ && (finfo->info->executable
++ || ! finfo->info->allow_shlib_undefined)
+ && h->root.type == bfd_link_hash_undefined
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+--- bfd/elf32-ppc.c.jj 2003-05-23 10:18:52.000000000 -0400
++++ bfd/elf32-ppc.c 2003-05-28 03:19:08.000000000 -0400
+@@ -2920,7 +2920,7 @@ ppc_elf_size_dynamic_sections (output_bf
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (htab->elf.dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+@@ -3102,7 +3102,7 @@ ppc_elf_size_dynamic_sections (output_bf
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf32-s390.c.jj 2003-05-15 16:42:24.000000000 -0400
++++ bfd/elf32-s390.c 2003-05-28 03:19:32.000000000 -0400
+@@ -1927,7 +1927,7 @@ elf_s390_size_dynamic_sections (output_b
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ if (s == NULL)
+@@ -2085,7 +2085,7 @@ elf_s390_size_dynamic_sections (output_b
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (! info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf64-ppc.c.jj 2003-05-23 10:18:52.000000000 -0400
++++ bfd/elf64-ppc.c 2003-05-28 03:19:51.000000000 -0400
+@@ -5737,7 +5737,7 @@ ppc64_elf_size_dynamic_sections (output_
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ if (s == NULL)
+@@ -5936,7 +5936,7 @@ ppc64_elf_size_dynamic_sections (output_
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf64-s390.c.jj 2003-05-15 16:42:25.000000000 -0400
++++ bfd/elf64-s390.c 2003-05-28 03:20:08.000000000 -0400
+@@ -1898,7 +1898,7 @@ elf_s390_size_dynamic_sections (output_b
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ if (s == NULL)
+@@ -2056,7 +2056,7 @@ elf_s390_size_dynamic_sections (output_b
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (! info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf64-x86-64.c.jj 2003-05-05 17:46:47.000000000 -0400
++++ bfd/elf64-x86-64.c 2003-05-28 05:44:30.000000000 -0400
+@@ -1618,7 +1618,7 @@ elf64_x86_64_size_dynamic_sections (outp
+ if (htab->elf.dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ if (s == NULL)
+@@ -1779,7 +1779,7 @@ elf64_x86_64_size_dynamic_sections (outp
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (! info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elfxx-ia64.c.jj 2003-05-15 16:42:25.000000000 -0400
++++ bfd/elfxx-ia64.c 2003-05-28 03:24:40.000000000 -0400
+@@ -2903,7 +2903,7 @@ elfNN_ia64_size_dynamic_sections (output
+
+ /* Set the contents of the .interp section to the interpreter. */
+ if (ia64_info->root.dynamic_sections_created
+- && !info->shared)
++ && info->executable)
+ {
+ sec = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (sec != NULL);
+@@ -3078,7 +3078,7 @@ elfNN_ia64_size_dynamic_sections (output
+ later (in finish_dynamic_sections) but we must add the entries now
+ so that we get the correct size for the .dynamic section. */
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ /* The DT_DEBUG entry is filled in by the dynamic linker and used
+ by the debugger. */
+--- bfd/elf32-sparc.c.jj 2003-05-28 03:03:45.000000000 -0400
++++ bfd/elf32-sparc.c 2003-05-28 03:20:48.000000000 -0400
+@@ -1820,7 +1820,7 @@ elf32_sparc_size_dynamic_sections (outpu
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+@@ -1997,7 +1997,7 @@ elf32_sparc_size_dynamic_sections (outpu
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf64-alpha.c.jj 2003-05-15 16:42:25.000000000 -0400
++++ bfd/elf64-alpha.c 2003-05-28 03:21:20.000000000 -0400
+@@ -4090,7 +4090,7 @@ elf64_alpha_size_dynamic_sections (outpu
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (!info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+@@ -4176,7 +4176,7 @@ elf64_alpha_size_dynamic_sections (outpu
+ #define add_dynamic_entry(TAG, VAL) \
+ bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elf64-sparc.c.jj 2003-05-28 03:03:45.000000000 -0400
++++ bfd/elf64-sparc.c 2003-05-28 03:21:59.000000000 -0400
+@@ -1781,7 +1781,7 @@ sparc64_elf_size_dynamic_sections (outpu
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+@@ -1880,7 +1880,7 @@ sparc64_elf_size_dynamic_sections (outpu
+ struct elf_strtab_hash *dynstr;
+ struct elf_link_hash_table *eht = elf_hash_table (info);
+
+- if (!info->shared)
++ if (info->executable)
+ {
+ if (!add_dynamic_entry (DT_DEBUG, 0))
+ return FALSE;
+--- bfd/elflink.c.jj 2003-05-23 10:18:52.000000000 -0400
++++ bfd/elflink.c 2003-05-28 06:20:40.000000000 -0400
+@@ -94,7 +94,7 @@ _bfd_elf_create_got_section (abfd, info)
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+- if (info->shared
++ if (! info->executable
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+
+@@ -144,7 +144,7 @@ _bfd_elf_link_create_dynamic_sections (a
+
+ /* A dynamically linked executable has a .interp section, but a
+ shared library does not. */
+- if (! info->shared)
++ if (info->executable)
+ {
+ s = bfd_make_section (abfd, ".interp");
+ if (s == NULL
+@@ -227,7 +227,7 @@ _bfd_elf_link_create_dynamic_sections (a
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+- if (info->shared
++ if (! info->executable
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+
+@@ -295,7 +295,7 @@ _bfd_elf_create_dynamic_sections (abfd,
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+- if (info->shared
++ if (! info->executable
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+@@ -1760,7 +1760,7 @@ _bfd_elf_link_assign_sym_version (h, dat
+
+ /* If we are building an application, we need to create a
+ version node for this version. */
+- if (t == NULL && ! info->shared)
++ if (t == NULL && info->executable)
+ {
+ struct bfd_elf_version_tree **pp;
+ int version_index;
+--- include/bfdlink.h.jj 2003-05-23 10:18:54.000000000 -0400
++++ include/bfdlink.h 2003-05-28 03:15:38.000000000 -0400
+@@ -291,6 +291,12 @@ struct bfd_link_info
+ /* TRUE if relaxation is being finalized. */
+ unsigned int relax_finalizing: 1;
+
++ /* TRUE if generating a position independent executable. */
++ unsigned int pie: 1;
++
++ /* TRUE if generating an executable, position independent or not. */
++ unsigned int executable : 1;
++
+ /* Which symbols to strip. */
+ enum bfd_link_strip strip;
+
+--- ld/emulparams/elf_i386.sh.jj 2002-03-07 14:52:39.000000000 -0500
++++ ld/emulparams/elf_i386.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -9,4 +9,5 @@ MACHINE=
+ NOP=0x90909090
+ TEMPLATE_NAME=elf32
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ NO_SMALL_DATA=yes
+--- ld/emulparams/elf64_ia64.sh.jj 2003-05-15 16:42:25.000000000 -0400
++++ ld/emulparams/elf64_ia64.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -16,6 +16,7 @@ fi
+ TEXT_START_ADDR="0x4000000000000000"
+ DATA_ADDR="0x6000000000000000 + (. & (${MAXPAGESIZE} - 1))"
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ NOP=0x00300000010070000002000001000400 # a bundle full of nops
+ OTHER_GOT_SECTIONS="
+ .IA_64.pltoff ${RELOCATING-0} : { *(.IA_64.pltoff) }"
+--- ld/emulparams/elf32ppc.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/emulparams/elf32ppc.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -4,6 +4,7 @@
+ TEMPLATE_NAME=elf32
+ EXTRA_EM_FILE=ppc32elf
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ SCRIPT_NAME=elf
+ OUTPUT_FORMAT="elf32-powerpc"
+ TEXT_START_ADDR=0x01800000
+--- ld/emulparams/elf64ppc.sh.jj 2003-01-21 13:21:34.000000000 -0500
++++ ld/emulparams/elf64ppc.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -2,6 +2,7 @@ TEMPLATE_NAME=elf32
+ EXTRA_EM_FILE=ppc64elf
+ ELFSIZE=64
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ SCRIPT_NAME=elf
+ OUTPUT_FORMAT="elf64-powerpc"
+ TEXT_START_ADDR=0x10000000
+--- ld/emulparams/elf_x86_64.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/emulparams/elf_x86_64.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -10,6 +10,7 @@ MACHINE=
+ NOP=0x90909090
+ TEMPLATE_NAME=elf32
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ NO_SMALL_DATA=yes
+
+ if [ "x${host}" = "x${target}" ]; then
+--- ld/emulparams/elf_s390.sh.jj 2002-03-07 14:52:39.000000000 -0500
++++ ld/emulparams/elf_s390.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -8,3 +8,4 @@ MACHINE=
+ NOP=0x07070707
+ TEMPLATE_NAME=elf32
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+--- ld/emulparams/elf64_sparc.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/emulparams/elf64_sparc.sh 2003-05-28 03:30:35.000000000 -0400
+@@ -8,6 +8,7 @@ ARCH="sparc:v9"
+ MACHINE=
+ DATA_PLT=
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ NOP=0x01000000
+ NO_SMALL_DATA=yes
+
+--- ld/emulparams/elf32_sparc.sh.jj 2002-03-07 14:52:39.000000000 -0500
++++ ld/emulparams/elf32_sparc.sh 2003-05-28 03:30:49.000000000 -0400
+@@ -10,4 +10,5 @@ MACHINE=
+ TEMPLATE_NAME=elf32
+ DATA_PLT=
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ NO_SMALL_DATA=yes
+--- ld/emulparams/elf64alpha.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/emulparams/elf64alpha.sh 2003-05-28 03:31:11.000000000 -0400
+@@ -11,6 +11,7 @@ NONPAGED_TEXT_START_ADDR="0x120000000"
+ ARCH=alpha
+ MACHINE=
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+ DATA_PLT=
+ # Note that the number is always big-endian, thus we have to
+ # reverse the digit string.
+--- ld/emulparams/elf64_s390.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/emulparams/elf64_s390.sh 2003-05-28 03:31:25.000000000 -0400
+@@ -9,6 +9,7 @@ MACHINE=
+ NOP=0x07070707
+ TEMPLATE_NAME=elf32
+ GENERATE_SHLIB_SCRIPT=yes
++GENERATE_PIE_SCRIPT=yes
+
+ # Treat a host that matches the target with the possible exception of "x"
+ # in the name as if it were native.
+--- ld/emultempl/elf32.em.jj 2003-05-28 03:03:45.000000000 -0400
++++ ld/emultempl/elf32.em 2003-05-28 05:37:00.000000000 -0400
+@@ -643,7 +643,7 @@ gld${EMULATION_NAME}_after_open ()
+ struct bfd_link_needed_list *needed, *l;
+
+ /* We only need to worry about this when doing a final link. */
+- if (link_info.relocateable || link_info.shared)
++ if (link_info.relocateable || !link_info.executable)
+ return;
+
+ /* Get the list of files which appear in DT_NEEDED entries in
+@@ -1181,7 +1181,7 @@ gld${EMULATION_NAME}_place_orphan (file,
+
+ /* If this is a final link, then always put .gnu.warning.SYMBOL
+ sections into the .text section to get them out of the way. */
+- if (! link_info.shared
++ if (link_info.executable
+ && ! link_info.relocateable
+ && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
+ && hold_text.os != NULL)
+@@ -1475,6 +1475,14 @@ if cmp -s ldscripts/${EMULATION_NAME}.x
+ echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
+ sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
+ fi
++if test -n "$GENERATE_PIE_SCRIPT" ; then
++if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
++echo ' ; else if (link_info.pie && link_info.combreloc) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c
++fi
++echo ' ; else if (link_info.pie) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c
++fi
+ if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+ if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+ echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c
+@@ -1512,6 +1520,18 @@ cat >>e${EMULATION_NAME}.c <<EOF
+ return "ldscripts/${EMULATION_NAME}.xn";
+ EOF
+ fi
++if test -n "$GENERATE_PIE_SCRIPT" ; then
++if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
++cat >>e${EMULATION_NAME}.c <<EOF
++ else if (link_info.pie && link_info.combreloc)
++ return "ldscripts/${EMULATION_NAME}.xdc";
++EOF
++fi
++cat >>e${EMULATION_NAME}.c <<EOF
++ else if (link_info.pie)
++ return "ldscripts/${EMULATION_NAME}.xd";
++EOF
++fi
+ if test -n "$GENERATE_SHLIB_SCRIPT" ; then
+ if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
+ cat >>e${EMULATION_NAME}.c <<EOF
+--- ld/scripttempl/elf.sc.jj 2003-05-28 03:03:45.000000000 -0400
++++ ld/scripttempl/elf.sc 2003-05-28 03:15:38.000000000 -0400
+@@ -180,8 +180,9 @@ ${RELOCATING- /* For some reason, the So
+ SECTIONS
+ {
+ /* Read-only sections, merged into text segment: */
+- ${CREATE_SHLIB-${RELOCATING+. = ${TEXT_BASE_ADDRESS};}}
++ ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${TEXT_BASE_ADDRESS};}}}
+ ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + SIZEOF_HEADERS;}}
++ ${CREATE_PIE+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR:-0} + SIZEOF_HEADERS;}}
+ ${CREATE_SHLIB-${INTERP}}
+ ${INITIAL_READONLY_SECTIONS}
+ ${TEXT_DYNAMIC+${DYNAMIC}}
+--- ld/lexsup.c.jj 2003-05-15 16:42:25.000000000 -0400
++++ ld/lexsup.c 2003-05-28 03:15:38.000000000 -0400
+@@ -139,6 +139,7 @@ int parsing_defsym = 0;
+ #define OPTION_NO_STRIP_DISCARDED (OPTION_STRIP_DISCARDED + 1)
+ #define OPTION_ACCEPT_UNKNOWN_INPUT_ARCH (OPTION_NO_STRIP_DISCARDED + 1)
+ #define OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH (OPTION_ACCEPT_UNKNOWN_INPUT_ARCH + 1)
++#define OPTION_PIE (OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH + 1)
+
+ /* The long options. This structure is used for both the option
+ parsing and the help text. */
+@@ -373,6 +374,10 @@ static const struct ld_option ld_options
+ '\0', NULL, N_("Create a shared library"), ONE_DASH },
+ { {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD. */
+ '\0', NULL, NULL, ONE_DASH },
++ { {"pie", no_argument, NULL, OPTION_PIE},
++ '\0', NULL, N_("Create a position independent executable"), ONE_DASH },
++ { {"pic-executable", no_argument, NULL, OPTION_PIE},
++ '\0', NULL, NULL, TWO_DASHES },
+ { {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
+ '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
+ { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
+@@ -958,6 +961,15 @@ parse_args (argc, argv)
+ else
+ einfo (_("%P%F: -shared not supported\n"));
+ break;
++ case OPTION_PIE:
++ if (config.has_shared)
++ {
++ link_info.shared = TRUE;
++ link_info.pie = TRUE;
++ }
++ else
++ einfo (_("%P%F: -pie not supported\n"));
++ break;
+ case 'h': /* Used on Solaris. */
+ case OPTION_SONAME:
+ command_line.soname = optarg;
+--- ld/genscripts.sh.jj 2003-03-19 12:19:16.000000000 -0500
++++ ld/genscripts.sh 2003-05-28 03:15:38.000000000 -0400
+@@ -227,6 +227,31 @@ if test -n "$GENERATE_SHLIB_SCRIPT"; the
+ rm -f ${COMBRELOC}
+ COMBRELOC=
+ fi
++ unset CREATE_SHLIB
++fi
++
++if test -n "$GENERATE_PIE_SCRIPT"; then
++ LD_FLAG=pie
++ DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
++ CREATE_PIE=" "
++ # Note that TEXT_START_ADDR is set to NONPAGED_TEXT_START_ADDR.
++ (
++ echo "/* Script for ld -pie: link position independent executable */"
++ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
++ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
++ ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xd
++ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
++ LD_FLAG=cpie
++ DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
++ COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
++ ( echo "/* Script for -pie -z combreloc: position independent executable, combine & sort relocs */"
++ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
++ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
++ ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xdc
++ rm -f ${COMBRELOC}
++ COMBRELOC=
++ fi
++ unset CREATE_PIE
+ fi
+
+ case " $EMULATION_LIBPATH " in
+--- ld/ldmain.c.jj 2003-05-15 16:42:25.000000000 -0400
++++ ld/ldmain.c 2003-05-28 03:15:38.000000000 -0400
+@@ -291,6 +291,8 @@ main (argc, argv)
+ link_info.emitrelocations = FALSE;
+ link_info.task_link = FALSE;
+ link_info.shared = FALSE;
++ link_info.pie = FALSE;
++ link_info.executable = FALSE;
+ link_info.symbolic = FALSE;
+ link_info.export_dynamic = FALSE;
+ link_info.static_link = FALSE;
+@@ -368,6 +370,9 @@ main (argc, argv)
+ einfo (_("%P%F: -f may not be used without -shared\n"));
+ }
+
++ if (! link_info.shared || link_info.pie)
++ link_info.executable = TRUE;
++
+ /* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
+ don't see how else this can be handled, since in this case we
+ must preserve all externally visible symbols. */
+--- ld/ld.texinfo.jj 2003-05-05 17:46:49.000000000 -0400
++++ ld/ld.texinfo 2003-05-29 07:35:25.000000000 -0400
+@@ -1209,6 +1209,18 @@ command @code{OUTPUT_FORMAT} can also sp
+ this option overrides it. @xref{BFD}.
+ @end ifclear
+
++@kindex -pie
++@kindex --pic-executable
++@item -pie
++@itemx --pic-executable
++@cindex position independent executables
++Create a position independent executable. This is currently only supported on
++ELF platforms. Position independent executables are similar to shared
++libraries in that they are relocated by the dynamic linker to the virtual
++address OS chooses for them (which can varry between invocations), like
++normal dynamically linked executables they can be executed and symbols
++defined in the executable cannot be overridden by shared libraries.
++
+ @kindex -qmagic
+ @item -qmagic
+ This option is ignored for Linux compatibility.
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie2.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie2.patch
new file mode 100644
index 000000000000..d523059d5514
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pie2.patch
@@ -0,0 +1,25 @@
+2003-06-06 Jakub Jelinek <jakub@redhat.com>
+
+ * elf-bfd.h (SYMBOL_REFERENCES_LOCAL, SYMBOL_CALLS_LOCAL): Return
+ true even if -pie.
+
+--- bfd/elf-bfd.h.jj 2003-06-03 18:25:09.000000000 -0400
++++ bfd/elf-bfd.h 2003-06-06 11:30:25.000000000 -0400
+@@ -217,7 +217,7 @@ struct elf_link_hash_entry
+ it's necessary for shared libs to also reference the .plt even
+ though the symbol is really local to the shared lib. */
+ #define SYMBOL_REFERENCES_LOCAL(INFO, H) \
+- ((! (INFO)->shared \
++ (((INFO)->executable \
+ || (INFO)->symbolic \
+ || (H)->dynindx == -1 \
+ || ELF_ST_VISIBILITY ((H)->other) == STV_INTERNAL \
+@@ -227,7 +227,7 @@ struct elf_link_hash_entry
+
+ /* Will _calls_ to this symbol always call the version in this object? */
+ #define SYMBOL_CALLS_LOCAL(INFO, H) \
+- ((! (INFO)->shared \
++ (((INFO)->executable \
+ || (INFO)->symbolic \
+ || (H)->dynindx == -1 \
+ || ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT \
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pni.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pni.patch
new file mode 100644
index 000000000000..13e675161613
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pni.patch
@@ -0,0 +1,442 @@
+gas/
+
+2003-05-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/config/tc-i386.c (md_assemble): Support Intel Precott New
+ Instructions.
+
+ * gas/config/tc-i386.h (CpuPNI): New.
+ (CpuUnknownFlags): Add CpuPNI.
+
+gas/testsuite/
+
+2003-05-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gas/i386/i386.exp: Add prescott.
+
+ * gas/i386/prescott.d: New file.
+ * gas/i386/prescott.s: Likewise.
+
+include/opcode/
+
+2003-05-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * i386.h (i386_optab): Support Intel Precott New Instructions.
+
+opcodes/
+
+2003-05-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ * i386-dis.c (PNI_Fixup): New. Fix up "mwait" and "monitor" in
+ Intel Precott New Instructions.
+ (PREGRP27): New. Added for "addsubpd" and "addsubps".
+ (PREGRP28): New. Added for "haddpd" and "haddps".
+ (PREGRP29): New. Added for "hsubpd" and "hsubps".
+ (PREGRP30): New. Added for "movsldup" and "movddup".
+ (PREGRP31): New. Added for "movshdup" and "movhpd".
+ (PREGRP32): New. Added for "lddqu".
+ (dis386_twobyte): Use PREGRP30 to replace the "movlpX" entry.
+ Use PREGRP31 to replace the "movhpX" entry. Use PREGRP28 for
+ entry 0x7c. Use PREGRP29 for entry 0x7d. Use PREGRP27 for
+ entry 0xd0. Use PREGRP32 for entry 0xf0.
+ (twobyte_has_modrm): Updated.
+ (twobyte_uses_SSE_prefix): Likewise.
+ (grps): Use PNI_Fixup in the "sidtQ" entry.
+ (prefix_user_table): Add PREGRP27, PREGRP28, PREGRP29, PREGRP30,
+ PREGRP31 and PREGRP32.
+ (float_mem): Use "fisttp{l||l|}" in entry 1 in opcode 0xdb.
+ Use "fisttpll" in entry 1 in opcode 0xdd.
+ Use "fisttp" in entry 1 in opcode 0xdf.
+
+--- gas/config/tc-i386.c.pni 2003-02-27 11:27:09.000000000 -0800
++++ gas/config/tc-i386.c 2003-05-05 08:27:55.000000000 -0700
+@@ -1392,6 +1392,21 @@ md_assemble (line)
+
+ if (i.tm.opcode_modifier & ImmExt)
+ {
++ if ((i.tm.cpu_flags & CpuPNI) && i.operands > 0)
++ {
++ /* These Intel Precott New Instructions have the fixed
++ operands with an opcode suffix which is coded in the same
++ place as an 8-bit immediate field would be. Here we check
++ those operands and remove them afterwards. */
++ unsigned int x;
++
++ for (x = 0; x < i.operands; x++)
++ if (i.op[x].regs->reg_num != x)
++ as_bad (_("can't use register '%%%s' as operand %d in '%s'."),
++ i.op[x].regs->reg_name, x + 1, i.tm.name);
++ i.operands = 0;
++ }
++
+ /* These AMD 3DNow! and Intel Katmai New Instructions have an
+ opcode suffix which is coded in the same place as an 8-bit
+ immediate field would be. Here we fake an 8-bit immediate
+--- gas/config/tc-i386.h.pni 2003-01-23 09:20:47.000000000 -0800
++++ gas/config/tc-i386.h 2003-05-05 08:27:55.000000000 -0700
+@@ -243,13 +243,14 @@ typedef struct
+ #define CpuSSE 0x1000 /* Streaming SIMD extensions required */
+ #define CpuSSE2 0x2000 /* Streaming SIMD extensions 2 required */
+ #define Cpu3dnow 0x4000 /* 3dnow! support required */
++#define CpuPNI 0x8000 /* Prescott New Instuctions required */
+
+ /* These flags are set by gas depending on the flag_code. */
+ #define Cpu64 0x4000000 /* 64bit support required */
+ #define CpuNo64 0x8000000 /* Not supported in the 64bit mode */
+
+ /* The default value for unknown CPUs - enable all features to avoid problems. */
+-#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|Cpu3dnow|CpuK6|CpuAthlon)
++#define CpuUnknownFlags (Cpu086|Cpu186|Cpu286|Cpu386|Cpu486|Cpu586|Cpu686|CpuP4|CpuSledgehammer|CpuMMX|CpuSSE|CpuSSE2|CpuPNI|Cpu3dnow|CpuK6|CpuAthlon)
+
+ /* the bits in opcode_modifier are used to generate the final opcode from
+ the base_opcode. These bits also are used to detect alternate forms of
+--- gas/testsuite/gas/i386/i386.exp.pni 2002-11-06 09:20:11.000000000 -0800
++++ gas/testsuite/gas/i386/i386.exp 2003-05-05 08:54:06.000000000 -0700
+@@ -56,6 +56,7 @@ if [expr ([istarget "i*86-*-*"] || [ist
+ run_dump_test "absrel"
+ run_dump_test "pcrel"
+ run_dump_test "sub"
++ run_dump_test "prescott"
+
+ # PIC is only supported on ELF targets.
+ if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"] )
+--- gas/testsuite/gas/i386/prescott.d.pni 2003-05-05 08:53:28.000000000 -0700
++++ gas/testsuite/gas/i386/prescott.d 2003-05-05 09:23:20.000000000 -0700
+@@ -0,0 +1,37 @@
++#objdump: -dw
++#name: i386 prescott
++
++.*: +file format .*
++
++Disassembly of section .text:
++
++0+000 <foo>:
++ 0: 66 0f d0 01 [ ]*addsubpd \(%ecx\),%xmm0
++ 4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
++ 8: f2 0f d0 13 [ ]*addsubps \(%ebx\),%xmm2
++ c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
++ 10: df 88 90 90 90 90 [ ]*fisttp 0x90909090\(%eax\)
++ 16: db 88 90 90 90 90 [ ]*fisttpl 0x90909090\(%eax\)
++ 1c: dd 88 90 90 90 90 [ ]*fisttpll 0x90909090\(%eax\)
++ 22: dd 88 90 90 90 90 [ ]*fisttpll 0x90909090\(%eax\)
++ 28: dd 88 90 90 90 90 [ ]*fisttpll 0x90909090\(%eax\)
++ 2e: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%ebp\),%xmm4
++ 33: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
++ 37: f2 0f 7c 37 [ ]*haddps \(%edi\),%xmm6
++ 3b: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
++ 3f: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
++ 43: 66 0f 7d 0a [ ]*hsubpd \(%edx\),%xmm1
++ 47: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
++ 4b: f2 0f 7d 1c 24 [ ]*hsubps \(%esp,1\),%xmm3
++ 50: f2 0f f0 2e [ ]*lddqu \(%esi\),%xmm5
++ 54: 0f 01 c8 [ ]*monitor %eax,%ecx,%edx
++ 57: 0f 01 c8 [ ]*monitor %eax,%ecx,%edx
++ 5a: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
++ 5e: f2 0f 12 38 [ ]*movddup \(%eax\),%xmm7
++ 62: f3 0f 16 01 [ ]*movshdup \(%ecx\),%xmm0
++ 66: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
++ 6a: f3 0f 12 13 [ ]*movsldup \(%ebx\),%xmm2
++ 6e: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
++ 72: 0f 01 c9 [ ]*mwait %eax,%ecx
++ 75: 0f 01 c9 [ ]*mwait %eax,%ecx
++ ...
+--- gas/testsuite/gas/i386/prescott.s.pni 2003-05-05 08:53:31.000000000 -0700
++++ gas/testsuite/gas/i386/prescott.s 2003-05-05 08:46:29.000000000 -0700
+@@ -0,0 +1,34 @@
++#Prescott New Instructions
++
++ .text
++foo:
++ addsubpd (%ecx),%xmm0
++ addsubpd %xmm2,%xmm1
++ addsubps (%ebx),%xmm2
++ addsubps %xmm4,%xmm3
++ fisttp 0x90909090(%eax)
++ fisttpl 0x90909090(%eax)
++ fisttpd 0x90909090(%eax)
++ fisttpq 0x90909090(%eax)
++ fisttpll 0x90909090(%eax)
++ haddpd 0x0(%ebp),%xmm4
++ haddpd %xmm6,%xmm5
++ haddps (%edi),%xmm6
++ haddps %xmm0,%xmm7
++ hsubpd %xmm1,%xmm0
++ hsubpd (%edx),%xmm1
++ hsubps %xmm2,%xmm2
++ hsubps (%esp,1),%xmm3
++ lddqu (%esi),%xmm5
++ monitor
++ monitor %eax,%ecx,%edx
++ movddup %xmm7,%xmm6
++ movddup (%eax),%xmm7
++ movshdup (%ecx),%xmm0
++ movshdup %xmm2,%xmm1
++ movsldup (%ebx),%xmm2
++ movsldup %xmm4,%xmm3
++ mwait
++ mwait %eax,%ecx
++
++ .p2align 4,0
+--- include/opcode/i386.h.pni 2002-07-08 08:39:20.000000000 -0700
++++ include/opcode/i386.h 2003-05-05 08:27:55.000000000 -0700
+@@ -1302,6 +1302,30 @@ static const template i386_optab[] = {
+ {"punpckhqdq",2, 0x660f6d, X, CpuSSE2, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
+ {"punpcklqdq",2, 0x660f6c, X, CpuSSE2, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
+
++/* Prescott New Instructions. */
++
++{"addsubpd", 2, 0x660fd0, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"addsubps", 2, 0xf20fd0, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"fisttp", 1, 0xdf, 1, CpuPNI, sl_FP|FloatMF|Modrm, { ShortMem|LongMem, 0, 0} },
++/* Intel Syntax */
++{"fisttpd", 1, 0xdd, 1, CpuPNI, FP|Modrm, { LLongMem, 0, 0} },
++{"fisttpq", 1, 0xdd, 1, CpuPNI, FP|Modrm, { LLongMem, 0, 0} },
++{"fisttpll", 1, 0xdd, 1, CpuPNI, FP|Modrm, { LLongMem, 0, 0} },
++{"haddpd", 2, 0x660f7c, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"haddps", 2, 0xf20f7c, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"hsubpd", 2, 0x660f7d, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"hsubps", 2, 0xf20f7d, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"lddqu", 2, 0xf20ff0, X, CpuPNI, FP|Modrm, { LLongMem, RegXMM, 0 } },
++{"monitor", 0, 0x0f01, 0xc8, CpuPNI, FP|ImmExt, { 0, 0, 0} },
++/* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
++{"monitor", 3, 0x0f01, 0xc8, CpuPNI, FP|ImmExt, { Reg32, Reg32, Reg32} },
++{"movddup", 2, 0xf20f12, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"movshdup", 2, 0xf30f16, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"movsldup", 2, 0xf30f12, X, CpuPNI, FP|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
++{"mwait", 0, 0x0f01, 0xc9, CpuPNI, FP|ImmExt, { 0, 0, 0} },
++/* Need to ensure only "mwait %eax,%ecx" is accepted. */
++{"mwait", 2, 0x0f01, 0xc9, CpuPNI, FP|ImmExt, { Reg32, Reg32, 0} },
++
+ /* AMD 3DNow! instructions. */
+
+ {"prefetch", 1, 0x0f0d, 0, Cpu3dnow, FP|Modrm, { ByteMem, 0, 0 } },
+--- opcodes/i386-dis.c.pni 2003-03-24 09:53:02.000000000 -0800
++++ opcodes/i386-dis.c 2003-05-05 08:27:55.000000000 -0700
+@@ -93,6 +93,7 @@ static void OP_XS PARAMS ((int, int));
+ static void OP_3DNowSuffix PARAMS ((int, int));
+ static void OP_SIMD_Suffix PARAMS ((int, int));
+ static void SIMD_Fixup PARAMS ((int, int));
++static void PNI_Fixup PARAMS ((int, int));
+ static void BadOp PARAMS ((void));
+
+ struct dis_private {
+@@ -417,6 +418,12 @@ fetch_data (info, addr)
+ #define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
+ #define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
+ #define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
++#define PREGRP27 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
++#define PREGRP28 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
++#define PREGRP29 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
++#define PREGRP30 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
++#define PREGRP31 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
++#define PREGRP32 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
+
+ #define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0
+
+@@ -776,11 +783,11 @@ static const struct dis386 dis386_twobyt
+ /* 10 */
+ { PREGRP8 },
+ { PREGRP9 },
+- { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
++ { PREGRP30 },
+ { "movlpX", EX, XM, SIMD_Fixup, 'h' },
+ { "unpcklpX", XM, EX, XX },
+ { "unpckhpX", XM, EX, XX },
+- { "movhpX", XM, EX, SIMD_Fixup, 'l' },
++ { PREGRP31 },
+ { "movhpX", EX, XM, SIMD_Fixup, 'l' },
+ /* 18 */
+ { GRP14 },
+@@ -895,8 +902,8 @@ static const struct dis386 dis386_twobyt
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+ { "(bad)", XX, XX, XX },
+- { "(bad)", XX, XX, XX },
+- { "(bad)", XX, XX, XX },
++ { PREGRP28 },
++ { PREGRP29 },
+ { PREGRP23 },
+ { PREGRP20 },
+ /* 80 */
+@@ -990,7 +997,7 @@ static const struct dis386 dis386_twobyt
+ { "bswap", RMeSI, XX, XX },
+ { "bswap", RMeDI, XX, XX },
+ /* d0 */
+- { "(bad)", XX, XX, XX },
++ { PREGRP27 },
+ { "psrlw", MX, EM, XX },
+ { "psrld", MX, EM, XX },
+ { "psrlq", MX, EM, XX },
+@@ -1026,7 +1033,7 @@ static const struct dis386 dis386_twobyt
+ { "pmaxsw", MX, EM, XX },
+ { "pxor", MX, EM, XX },
+ /* f0 */
+- { "(bad)", XX, XX, XX },
++ { PREGRP32 },
+ { "psllw", MX, EM, XX },
+ { "pslld", MX, EM, XX },
+ { "psllq", MX, EM, XX },
+@@ -1078,15 +1085,15 @@ static const unsigned char twobyte_has_m
+ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
+ /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
+ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
+- /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, /* 7f */
++ /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
+ /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */
+ /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
+ /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
+- /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
++ /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+ /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+- /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
++ /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+@@ -1095,21 +1102,21 @@ static const unsigned char twobyte_uses_
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+- /* 10 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */
++ /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
+ /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
+ /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
+ /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+ /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
+ /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
+- /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */
++ /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 7f */
+ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+ /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+ /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+ /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+ /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
+- /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
++ /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
+ /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
+- /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
++ /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+@@ -1349,7 +1356,7 @@ static const struct dis386 grps[][8] = {
+ /* GRP7 */
+ {
+ { "sgdtQ", M, XX, XX },
+- { "sidtQ", M, XX, XX },
++ { "sidtQ", PNI_Fixup, 0, XX, XX },
+ { "lgdtQ", M, XX, XX },
+ { "lidtQ", M, XX, XX },
+ { "smswQ", Ev, XX, XX },
+@@ -1638,6 +1645,48 @@ static const struct dis386 prefix_user_t
+ { "punpcklqdq", XM, EX, XX },
+ { "(bad)", XM, EX, XX },
+ },
++ /* PREGRP27 */
++ {
++ { "(bad)", MX, EX, XX },
++ { "(bad)", XM, EX, XX },
++ { "addsubpd", XM, EX, XX },
++ { "addsubps", XM, EX, XX },
++ },
++ /* PREGRP28 */
++ {
++ { "(bad)", MX, EX, XX },
++ { "(bad)", XM, EX, XX },
++ { "haddpd", XM, EX, XX },
++ { "haddps", XM, EX, XX },
++ },
++ /* PREGRP29 */
++ {
++ { "(bad)", MX, EX, XX },
++ { "(bad)", XM, EX, XX },
++ { "hsubpd", XM, EX, XX },
++ { "hsubps", XM, EX, XX },
++ },
++ /* PREGRP30 */
++ {
++ { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
++ { "movsldup", XM, EX, XX },
++ { "movlpd", XM, EX, XX },
++ { "movddup", XM, EX, XX },
++ },
++ /* PREGRP31 */
++ {
++ { "movhpX", XM, EX, SIMD_Fixup, 'l' },
++ { "movshdup", XM, EX, XX },
++ { "movhpd", XM, EX, XX },
++ { "(bad)", XM, EX, XX },
++ },
++ /* PREGRP32 */
++ {
++ { "(bad)", XM, EX, XX },
++ { "(bad)", XM, EX, XX },
++ { "(bad)", XM, EX, XX },
++ { "lddqu", XM, M, XX },
++ },
+ };
+
+ static const struct dis386 x86_64_table[][2] = {
+@@ -2294,7 +2343,7 @@ static const char *float_mem[] = {
+ "fidivr{l||l|}",
+ /* db */
+ "fild{l||l|}",
+- "(bad)",
++ "fisttp{l||l|}",
+ "fist{l||l|}",
+ "fistp{l||l|}",
+ "(bad)",
+@@ -2312,7 +2361,7 @@ static const char *float_mem[] = {
+ "fdivr{l||l|}",
+ /* dd */
+ "fld{l||l|}",
+- "(bad)",
++ "fisttpll",
+ "fst{l||l|}",
+ "fstp{l||l|}",
+ "frstor",
+@@ -2330,7 +2379,7 @@ static const char *float_mem[] = {
+ "fidivr",
+ /* df */
+ "fild",
+- "(bad)",
++ "fisttp",
+ "fist",
+ "fistp",
+ "fbld",
+@@ -4138,6 +4187,33 @@ SIMD_Fixup (extrachar, sizeflag)
+ }
+
+ static void
++PNI_Fixup (extrachar, sizeflag)
++ int extrachar ATTRIBUTE_UNUSED;
++ int sizeflag ATTRIBUTE_UNUSED;
++{
++ if (mod == 3 && reg == 1)
++ {
++ char *p = obuf + strlen (obuf);
++
++ /* Override "sidt". */
++ if (rm)
++ {
++ /* mwait %eax,%ecx */
++ strcpy (p - 4, "mwait %eax,%ecx");
++ }
++ else
++ {
++ /* monitor %eax,%ecx,%edx" */
++ strcpy (p - 4, "monitor %eax,%ecx,%edx");
++ }
++
++ codep++;
++ }
++ else
++ OP_E (0, sizeflag);
++}
++
++static void
+ BadOp (void)
+ {
+ /* Throw away prefixes and 1st. opcode byte. */
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc-bigplt.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc-bigplt.patch
new file mode 100644
index 000000000000..2689ef78c390
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc-bigplt.patch
@@ -0,0 +1,16 @@
+2003-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * elf32-ppc.c (allocate_dynrelocs): Use single slot for first 8192
+ plt entries, not just 8191.
+
+--- bfd/elf32-ppc.c.jj 2003-05-30 11:19:17.000000000 -0400
++++ bfd/elf32-ppc.c 2003-05-30 18:22:31.000000000 -0400
+@@ -2719,7 +2719,7 @@ allocate_dynrelocs (h, inf)
+ for two entries is allocated. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+ if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
+- >= PLT_NUM_SINGLE_ENTRIES)
++ > PLT_NUM_SINGLE_ENTRIES)
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .rela.plt section. */
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-ctors.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-ctors.patch
new file mode 100644
index 000000000000..339fb690b5f0
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-ctors.patch
@@ -0,0 +1,20 @@
+2003-06-10 Alan Modra <amodra@bigpond.net.au>
+
+ * emulparams/elf64ppc.sh (EXECUTABLE_SYMBOLS, OTHER_BSS_END_SYMBOLS,
+ CTOR_START, CTOR_END, DTOR_START, DTOR_END): Don't define.
+
+--- ld/emulparams/elf64ppc.sh 30 May 2003 15:50:11 -0000
++++ ld/emulparams/elf64ppc.sh 10 Jun 2003 04:27:28 -0000
+@@ -12,12 +12,6 @@ COMMONPAGESIZE=0x1000
+ ARCH=powerpc:common64
+ MACHINE=
+ NOP=0x60000000
+-EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);'
+-OTHER_BSS_END_SYMBOLS='__end = .;'
+-CTOR_START='PROVIDE (__CTOR_LIST__ = .); PROVIDE (___CTOR_LIST__ = .);'
+-CTOR_END='PROVIDE (__CTOR_END__ = .); PROVIDE (___CTOR_END__ = .);'
+-DTOR_START='PROVIDE (__DTOR_LIST__ = .); PROVIDE (___DTOR_LIST__ = .);'
+-DTOR_END='PROVIDE (__DTOR_END__ = .); PROVIDE (___DTOR_END__ = .);'
+ OTHER_TEXT_SECTIONS="*(.sfpr .glink)"
+ BSS_PLT=
+ OTHER_BSS_SYMBOLS="
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-prelink.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-prelink.patch
new file mode 100644
index 000000000000..db21d8899ae4
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-ppc64-prelink.patch
@@ -0,0 +1,132 @@
+2003-06-17 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c (ppc64_elf_relocate_section): Correct pcrel section zero.
+
+2003-06-16 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c (ppc64_elf_relocate_section): When optimizing toctprel
+ tls, check that a TOC16_DS or TOC16_LO_DS reloc isn't pointing to a
+ dtprel entry. Ensure TLS_LD DTPMOD reloc has a zero addend. Write
+ got section for RELATIVE relocs. Fix wrong comment. Change condition
+ under which dynamic relocs update the section contents.
+
+--- bfd/elf64-ppc.c 10 Jun 2003 07:44:09 -0000 1.101
++++ bfd/elf64-ppc.c 16 Jun 2003 10:50:22 -0000 1.102
+@@ -7153,7 +7153,11 @@ ppc64_elf_relocate_section (output_bfd,
+ tls_mask = *toc_tls;
+ if (r_type == R_PPC64_TOC16_DS
+ || r_type == R_PPC64_TOC16_LO_DS)
+- goto toctprel;
++ {
++ if (tls_mask != 0
++ && (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0)
++ goto toctprel;
++ }
+ else
+ {
+ /* If we found a GD reloc pair, then we might be
+@@ -7176,11 +7180,11 @@ ppc64_elf_relocate_section (output_bfd,
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+- toctprel:
+ if (tls_mask != 0
+ && (tls_mask & TLS_TPREL) == 0)
+ {
+ bfd_vma insn;
++ toctprel:
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2);
+ insn &= 31 << 21;
+ insn |= 0x3c0d0000; /* addis 0,13,0 */
+@@ -7653,6 +7657,7 @@ ppc64_elf_relocate_section (output_bfd,
+ outrel.r_offset = (htab->sgot->output_section->vma
+ + htab->sgot->output_offset
+ + off);
++ outrel.r_addend = rel->r_addend;
+ if (tls_type & (TLS_LD | TLS_GD))
+ {
+ outrel.r_addend = 0;
+@@ -7665,6 +7670,7 @@ ppc64_elf_relocate_section (output_bfd,
+ bfd_elf64_swap_reloca_out (output_bfd,
+ &outrel, loc);
+ outrel.r_offset += 8;
++ outrel.r_addend = rel->r_addend;
+ outrel.r_info
+ = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
+ }
+@@ -7674,11 +7680,18 @@ ppc64_elf_relocate_section (output_bfd,
+ else if (tls_type == (TLS_TLS | TLS_TPREL))
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64);
+ else if (indx == 0)
+- outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
++ {
++ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
++
++ /* Write the .got section contents for the sake
++ of prelink. */
++ loc = htab->sgot->contents + off;
++ bfd_put_64 (output_bfd, outrel.r_addend + relocation, loc);
++ }
+ else
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
+- outrel.r_addend = rel->r_addend;
+- if (indx == 0)
++
++ if (indx == 0 && tls_type != (TLS_TLS | TLS_LD))
+ {
+ outrel.r_addend += relocation;
+ if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
+@@ -7921,8 +7934,6 @@ ppc64_elf_relocate_section (output_bfd,
+ or this is an opd section reloc which must point
+ at a local function. */
+ outrel.r_addend += relocation;
+- /* ??? why? */
+- relocate = TRUE;
+ if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
+ {
+ if (is_opd && h != NULL)
+@@ -7940,6 +7951,12 @@ ppc64_elf_relocate_section (output_bfd,
+ unresolved_reloc = FALSE;
+ }
+ outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
++
++ /* We need to relocate .opd contents for ld.so.
++ Prelink also wants simple and consistent rules
++ for relocs. This make all RELATIVE relocs have
++ *r_offset equal to r_addend. */
++ relocate = TRUE;
+ }
+ else
+ {
+@@ -7981,9 +7998,29 @@ ppc64_elf_relocate_section (output_bfd,
+
+ /* If this reloc is against an external symbol, it will
+ be computed at runtime, so there's no need to do
+- anything now. */
++ anything now. However, for the sake of prelink ensure
++ that the section contents are a known value. */
+ if (! relocate)
+- continue;
++ {
++ unresolved_reloc = FALSE;
++ /* The value chosen here is quite arbitrary as ld.so
++ ignores section contents except for the special
++ case of .opd where the contents might be accessed
++ before relocation. Choose zero, as that won't
++ cause reloc overflow. */
++ relocation = 0;
++ addend = 0;
++ /* Use *r_offset == r_addend for R_PPC64_ADDR64 relocs
++ to improve backward compatibility with older
++ versions of ld. */
++ if (r_type == R_PPC64_ADDR64)
++ addend = outrel.r_addend;
++ /* Adjust pc_relative relocs to have zero in *r_offset. */
++ else if (ppc64_elf_howto_table[(int) r_type]->pc_relative)
++ addend = (input_section->output_section->vma
++ + input_section->output_offset
++ + rel->r_offset);
++ }
+ }
+ break;
+
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pt-gnu-stack.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pt-gnu-stack.patch
new file mode 100644
index 000000000000..d6cfd392dc44
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-pt-gnu-stack.patch
@@ -0,0 +1,235 @@
+2003-06-03 Jakub Jelinek <jakub@redhat.com>
+
+binutils/
+ * readelf.c (get_segment_type): Handle PT_GNU_STACK.
+bfd/
+ * elf.c (_bfd_elf_print_private_bfd_data): Handle PT_GNU_STACK.
+ (bfd_section_from_phdr): Likewise.
+ (map_sections_to_segments): Create PT_GNU_STACK segment header.
+ (get_program_header_size): Count with PT_GNU_STACK.
+ * elf-bfd.h (struct elf_obj_tdata): Add stack_flags.
+ * elflink.h (bfd_elfNN_size_dynamic_sections): Set stack_flags.
+include/
+ * bfdlink.h (struct bfd_link_info): Add execstack and noexecstack.
+ * elf/common.h (PT_GNU_STACK): Define.
+ld/
+ * ldgram.y (phdr_type): Grok PT_GNU_STACK.
+ * emultempl/elf32.em (gld${EMULATION_NAME}_handle_option): Add
+ -z execstack and -z noexecstack.
+ (gld${EMULATION_NAME}_list_options): Likewise.
+ * scripttempl/elf.sc: If not -r, discard .note.GNU-stack section.
+
+--- binutils/readelf.c.jj 2003-05-23 09:24:40.000000000 -0400
++++ binutils/readelf.c 2003-05-23 10:50:05.000000000 -0400
+@@ -2307,6 +2307,7 @@ get_segment_type (p_type)
+
+ case PT_GNU_EH_FRAME:
+ return "GNU_EH_FRAME";
++ case PT_GNU_STACK: return "STACK";
+
+ default:
+ if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
+--- bfd/elf.c.jj 2003-05-23 09:24:39.000000000 -0400
++++ bfd/elf.c 2003-05-23 16:15:02.000000000 -0400
+@@ -1070,6 +1070,7 @@ _bfd_elf_print_private_bfd_data (abfd, f
+ case PT_PHDR: pt = "PHDR"; break;
+ case PT_TLS: pt = "TLS"; break;
+ case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
++ case PT_GNU_STACK: pt = "STACK"; break;
+ default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
+ }
+ fprintf (f, "%8s off 0x", pt);
+@@ -2296,6 +2297,9 @@ bfd_section_from_phdr (abfd, hdr, index)
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+ "eh_frame_hdr");
+
++ case PT_GNU_STACK:
++ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
++
+ default:
+ /* Check for any processor-specific program segment types.
+ If no handler for them, default to making "segment" sections. */
+@@ -3513,6 +3517,21 @@ map_sections_to_segments (abfd)
+ pm = &m->next;
+ }
+
++ if (elf_tdata (abfd)->stack_flags)
++ {
++ amt = sizeof (struct elf_segment_map);
++ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
++ if (m == NULL)
++ goto error_return;
++ m->next = NULL;
++ m->p_type = PT_GNU_STACK;
++ m->p_flags = elf_tdata (abfd)->stack_flags;
++ m->p_flags_valid = 1;
++
++ *pm = m;
++ pm = &m->next;
++ }
++
+ free (sections);
+ sections = NULL;
+
+@@ -4099,6 +4118,12 @@ get_program_header_size (abfd)
+ ++segs;
+ }
+
++ if (elf_tdata (abfd)->stack_flags)
++ {
++ /* We need a PT_GNU_STACK segment. */
++ ++segs;
++ }
++
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LOAD) != 0
+--- bfd/elf-bfd.h.jj 2003-05-23 09:24:39.000000000 -0400
++++ bfd/elf-bfd.h 2003-05-23 10:30:28.000000000 -0400
+@@ -1254,6 +1254,9 @@ struct elf_obj_tdata
+ /* Number of symbol version references we are about to emit. */
+ unsigned int cverrefs;
+
++ /* Segment flags for the PT_GNU_STACK segment. */
++ unsigned int stack_flags;
++
+ /* Symbol version definitions in external objects. */
+ Elf_Internal_Verdef *verdef;
+
+--- bfd/elflink.h.jj 2003-05-23 09:24:40.000000000 -0400
++++ bfd/elflink.h 2003-05-23 16:35:55.000000000 -0400
+@@ -1937,6 +1937,43 @@ NAME(bfd_elf,size_dynamic_sections) (out
+ if (! is_elf_hash_table (info))
+ return TRUE;
+
++ if (info->execstack)
++ elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
++ else if (info->noexecstack)
++ elf_tdata (output_bfd)->stack_flags = PF_R | PF_W;
++ else
++ {
++ bfd *inputobj;
++ asection *notesec = NULL;
++ int exec = 0;
++
++ for (inputobj = info->input_bfds;
++ inputobj;
++ inputobj = inputobj->link_next)
++ {
++ asection *s;
++
++ if (inputobj->flags & DYNAMIC)
++ continue;
++ s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
++ if (s)
++ {
++ if (s->flags & SEC_CODE)
++ exec = PF_X;
++ notesec = s;
++ }
++ else
++ exec = PF_X;
++ }
++ if (notesec)
++ {
++ elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | exec;
++ if (exec && info->relocateable
++ && notesec->output_section != bfd_abs_section_ptr)
++ notesec->output_section->flags |= SEC_CODE;
++ }
++ }
++
+ /* Any syms created from now on start with -1 in
+ got.refcount/offset and plt.refcount/offset. */
+ elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset;
+--- include/bfdlink.h.jj 2003-05-23 09:24:43.000000000 -0400
++++ include/bfdlink.h 2003-05-23 10:07:06.000000000 -0400
+@@ -291,6 +291,14 @@ struct bfd_link_info
+ /* TRUE if relaxation is being finalized. */
+ unsigned int relax_finalizing: 1;
+
++ /* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W|PF_X
++ flags. */
++ unsigned int execstack: 1;
++
++ /* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W
++ flags. */
++ unsigned int noexecstack: 1;
++
+ /* Which symbols to strip. */
+ enum bfd_link_strip strip;
+
+--- include/elf/common.h.jj 2003-05-23 09:24:43.000000000 -0400
++++ include/elf/common.h 2003-05-23 09:32:48.000000000 -0400
+@@ -288,6 +288,7 @@
+ #define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+
+ #define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
++#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+
+ /* Program segment permissions, in program header p_flags field. */
+
+--- ld/ldgram.y.jj 2003-05-05 18:28:06.000000000 -0400
++++ ld/ldgram.y 2003-05-23 16:52:09.000000000 -0400
+@@ -1006,6 +1006,8 @@ phdr_type:
+ {
+ if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
+ $$ = exp_intop (0x6474e550);
++ else if (strcmp (s, "PT_GNU_STACK") == 0)
++ $$ = exp_intop (0x6474e551);
+ else
+ {
+ einfo (_("\
+--- ld/emultempl/elf32.em.jj 2003-05-19 17:12:46.000000000 -0400
++++ ld/emultempl/elf32.em 2003-05-23 10:08:07.000000000 -0400
+@@ -1664,6 +1664,16 @@ cat >>e${EMULATION_NAME}.c <<EOF
+ link_info.combreloc = FALSE;
+ else if (strcmp (optarg, "nocopyreloc") == 0)
+ link_info.nocopyreloc = TRUE;
++ else if (strcmp (optarg, "execstack") == 0)
++ {
++ link_info.execstack = TRUE;
++ link_info.noexecstack = FALSE;
++ }
++ else if (strcmp (optarg, "noexecstack") == 0)
++ {
++ link_info.noexecstack = TRUE;
++ link_info.execstack = FALSE;
++ }
+ /* What about the other Solaris -z options? FIXME. */
+ break;
+ EOF
+@@ -1702,6 +1712,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
+ fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n"));
+ fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n"));
+ fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n"));
++ fprintf (file, _(" -z execstack\t\tMark executable as requiring executable stack\n"));
+ fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n"));
+ fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n"));
+ fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n"));
+@@ -1712,6 +1723,7 @@ cat >>e${EMULATION_NAME}.c <<EOF
+ fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n"));
+ fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n"));
+ fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n"));
++ fprintf (file, _(" -z noexecstack\t\tMark executable as not requiring executable stack\n"));
+ fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n"));
+ fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n"));
+ fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n"));
+--- ld/scripttempl/elf.sc.jj 2003-04-14 10:57:55.000000000 -0400
++++ ld/scripttempl/elf.sc 2003-05-23 16:23:06.000000000 -0400
+@@ -84,6 +84,7 @@ INTERP=".interp ${RELOCATING-0} :
+ PLT=".plt ${RELOCATING-0} : { *(.plt) }"
+ DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
+ RODATA=".rodata ${RELOCATING-0} : { *(.rodata${RELOCATING+ .rodata.* .gnu.linkonce.r.*}) }"
++STACKNOTE="/DISCARD/ : { *(.note.GNU-stack) }"
+ if test -z "${NO_SMALL_DATA}"; then
+ SBSS=".sbss ${RELOCATING-0} :
+ {
+@@ -395,5 +396,6 @@ cat <<EOF
+ ${STACK_ADDR+${STACK}}
+ ${OTHER_SECTIONS}
+ ${RELOCATING+${OTHER_END_SYMBOLS}}
++ ${RELOCATING+${STACKNOTE}}
+ }
+ EOF
+
diff --git a/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-sparc-nonpic.patch b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-sparc-nonpic.patch
new file mode 100644
index 000000000000..78b55fe1e398
--- /dev/null
+++ b/sys-devel/binutils/files/2.14/binutils-2.14.90.0.4-sparc-nonpic.patch
@@ -0,0 +1,94 @@
+2002-04-20 Jakub Jelinek <jakub@redhat.com>
+
+ * elf32-sparc.c (elf32_sparc_relocate_section): Find real output
+ section with SEC_MERGE.
+ * elf64-sparc.c (sparc64_elf_relocate_section): Likewise.
+
+--- bfd/elf32-sparc.c.jj Thu Feb 6 08:07:10 2003
++++ bfd/elf32-sparc.c Thu Feb 6 08:31:54 2003
+@@ -2168,7 +2168,7 @@ elf32_sparc_relocate_section (output_bfd
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+- bfd_vma relocation, off;
++ bfd_vma relocation, off, orig_addend = 0;
+ bfd_reloc_status_type r;
+ bfd_boolean is_plt = FALSE;
+ bfd_boolean unresolved_reloc;
+@@ -2196,6 +2196,7 @@ elf32_sparc_relocate_section (output_bfd
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
++ orig_addend = rel->r_addend;
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ }
+ else
+@@ -2525,6 +2526,24 @@ elf32_sparc_relocate_section (output_bfd
+ asection *osec;
+
+ osec = sec->output_section;
++ /* FIXME: As soon as making sections zero size
++ is possible, this if can go away. */
++ if (bfd_is_abs_section (osec)
++ && h == NULL
++ && (sec->flags & SEC_MERGE)
++ && ELF_ST_TYPE (sym->st_info) == STT_SECTION
++ && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
++ {
++ asection *msec;
++
++ msec = sec;
++ _bfd_merged_section_offset (output_bfd, &msec,
++ elf_section_data (sec)->sec_info,
++ sym->st_value + orig_addend,
++ (bfd_vma) 0);
++ osec = msec->output_section;
++ }
++
+ indx = elf_section_data (osec)->dynindx;
+
+ /* FIXME: we really should be able to link non-pic
+--- bfd/elf64-sparc.c.jj Thu Feb 6 08:07:10 2003
++++ bfd/elf64-sparc.c Thu Feb 6 08:31:54 2003
+@@ -2016,7 +2016,7 @@ sparc64_elf_relocate_section (output_bfd
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+- bfd_vma relocation, off;
++ bfd_vma relocation, off, orig_addend = 0;
+ bfd_reloc_status_type r;
+ bfd_boolean is_plt = FALSE;
+ bfd_boolean unresolved_reloc;
+@@ -2039,6 +2039,7 @@ sparc64_elf_relocate_section (output_bfd
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
++ orig_addend = rel->r_addend;
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ }
+ else
+@@ -2267,6 +2268,24 @@ sparc64_elf_relocate_section (output_bfd
+ asection *osec;
+
+ osec = sec->output_section;
++ /* FIXME: As soon as making sections zero size
++ is possible, this if can go away. */
++ if (bfd_is_abs_section (osec)
++ && h == NULL
++ && (sec->flags & SEC_MERGE)
++ && ELF_ST_TYPE (sym->st_info) == STT_SECTION
++ && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
++ {
++ asection *msec;
++
++ msec = sec;
++ _bfd_merged_section_offset (output_bfd, &msec,
++ elf_section_data (sec)->sec_info,
++ sym->st_value + orig_addend,
++ (bfd_vma) 0);
++ osec = msec->output_section;
++ }
++
+ indx = elf_section_data (osec)->dynindx;
+
+ /* We are turning this relocation into one