[openwrt/openwrt] toolchain/binutils: backport stable patches

LEDE Commits lede-commits at lists.infradead.org
Sun Jan 1 10:02:00 PST 2023


hauke pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/cabdbc632ecd41cf0917001f86b5e62e15a01ff0

commit cabdbc632ecd41cf0917001f86b5e62e15a01ff0
Author: Hauke Mehrtens <hauke at hauke-m.de>
AuthorDate: Sat Dec 31 21:11:35 2022 +0100

    toolchain/binutils: backport stable patches
    
    Add the patches with real changes from the binutils 2.39 stable branch.
    I am not aware that we ran into any of these problems, but I think it is
    better to take the existing stable patches.
    
    They were exported like this:
    git format-patch binutils-2_39...origin/binutils-2_39-branch
    I removed the patches changing the version numbers only.
    
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 .../patches/2.39/005-ld-fix-NEWS-typos.patch       |  27 ++
 ...s-Dwarf-properly-skip-zero-size-functions.patch |  90 ++++++
 ...ernal-error-in-relocate-at-powerpc.cc-107.patch | 270 ++++++++++++++++++
 .../011-PR29466-APP-NO_APP-with-.linefile.patch    | 167 ++++++++++++
 ...oongArch-ld-Fix-relocation-error-of-pcrel.patch | 128 +++++++++
 .../043-Re-PR29466-APP-NO_APP-with-linefile.patch  |  27 ++
 ...64-pcrel-got-relocs-against-local-symbols.patch |  38 +++
 ...64-pcrel-got-relocs-against-local-symbols.patch |  94 +++++++
 ...-Reset-alignment-for-each-PT_LOAD-segment.patch |  89 ++++++
 ...erPC-gold-internal-error-in-get_output_vi.patch |  29 ++
 ...RF-numbering-convention-for-pseudo-regist.patch | 301 +++++++++++++++++++++
 11 files changed, 1260 insertions(+)

diff --git a/toolchain/binutils/patches/2.39/005-ld-fix-NEWS-typos.patch b/toolchain/binutils/patches/2.39/005-ld-fix-NEWS-typos.patch
new file mode 100644
index 0000000000..39c61d9319
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/005-ld-fix-NEWS-typos.patch
@@ -0,0 +1,27 @@
+From 9284b63ea39cecbfc1522d9e143ecb7727d77eb5 Mon Sep 17 00:00:00 2001
+From: Martin Liska <mliska at suse.cz>
+Date: Mon, 8 Aug 2022 13:22:26 +0200
+Subject: [PATCH 005/160] ld: fix NEWS typos
+
+ld/ChangeLog:
+
+	* NEWS: Fix 2 typos.
+---
+ ld/NEWS | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/ld/NEWS
++++ b/ld/NEWS
+@@ -27,10 +27,10 @@ Changes in 2.39:
+   --enable-warn-rwx-segments=no
+      will make --no-warn-rwx-segments enabled by default.
+      
+-  --enable-defaul-execstack=no
++  --enable-default-execstack=no
+      will stop the creation of an executable stack simply because an input file
+      is missing a .note.GNU-stack section, even on architectures where this
+-     ehaviour is the default.
++     behaviour is the default.
+ 
+ * TYPE=<type> is now supported in an output section description to set the
+   section type value.
diff --git a/toolchain/binutils/patches/2.39/008-gas-Dwarf-properly-skip-zero-size-functions.patch b/toolchain/binutils/patches/2.39/008-gas-Dwarf-properly-skip-zero-size-functions.patch
new file mode 100644
index 0000000000..055da84129
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/008-gas-Dwarf-properly-skip-zero-size-functions.patch
@@ -0,0 +1,90 @@
+From e8cf73215187b0c08679d726a5cc7c019fa3ea2e Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich at suse.com>
+Date: Wed, 10 Aug 2022 10:34:22 +0200
+Subject: [PATCH 008/160] gas/Dwarf: properly skip zero-size functions
+
+PR gas/29451
+
+While out_debug_abbrev() properly skips such functions, out_debug_info()
+mistakenly didn't. It needs to calculate the high_pc expression ahead of
+time, in order to skip emitting any data for the function if the value
+is zero.
+
+The one case which would still leave a zero-size entry is when
+symbol_get_obj(symp)->size ends up evaluating to zero. I hope we can
+expect that to not be the case, otherwise we'd need to have a way to
+post-process .debug_info contents between resolving expressions and
+actually writing the data out to the file. Even then it wouldn't be
+entirely obvious in which way to alter the data.
+
+(cherry picked from commit d7abcbcea5ddd40a3bf28758b62f35933c59f996)
+---
+ gas/dwarf2dbg.c | 39 ++++++++++++++++++++-------------------
+ 1 file changed, 20 insertions(+), 19 deletions(-)
+
+--- a/gas/dwarf2dbg.c
++++ b/gas/dwarf2dbg.c
+@@ -2882,6 +2882,7 @@ out_debug_info (segT info_seg, segT abbr
+ 	{
+ 	  const char *name;
+ 	  size_t len;
++	  expressionS size = { .X_op = O_constant };
+ 
+ 	  /* Skip warning constructs (see above).  */
+ 	  if (symbol_get_bfdsym (symp)->flags & BSF_WARNING)
+@@ -2895,6 +2896,18 @@ out_debug_info (segT info_seg, segT abbr
+ 	  if (!S_IS_DEFINED (symp) || !S_IS_FUNCTION (symp))
+ 	    continue;
+ 
++#if defined (OBJ_ELF) /* || defined (OBJ_MAYBE_ELF) */
++	  size.X_add_number = S_GET_SIZE (symp);
++	  if (size.X_add_number == 0 && IS_ELF
++	      && symbol_get_obj (symp)->size != NULL)
++	    {
++	      size.X_op = O_add;
++	      size.X_op_symbol = make_expr_symbol (symbol_get_obj (symp)->size);
++	    }
++#endif
++	  if (size.X_op == O_constant && size.X_add_number == 0)
++	    continue;
++
+ 	  subseg_set (str_seg, 0);
+ 	  name_sym = symbol_temp_new_now_octets ();
+ 	  name = S_GET_NAME (symp);
+@@ -2920,29 +2933,17 @@ out_debug_info (segT info_seg, segT abbr
+ 	  emit_expr (&exp, sizeof_address);
+ 
+ 	  /* DW_AT_high_pc */
+-	  exp.X_op = O_constant;
+-#if defined (OBJ_ELF) /* || defined (OBJ_MAYBE_ELF) */
+-	  exp.X_add_number = S_GET_SIZE (symp);
+-	  if (exp.X_add_number == 0 && IS_ELF
+-	      && symbol_get_obj (symp)->size != NULL)
+-	    {
+-	      exp.X_op = O_add;
+-	      exp.X_op_symbol = make_expr_symbol (symbol_get_obj (symp)->size);
+-	    }
+-#else
+-	  exp.X_add_number = 0;
+-#endif
+ 	  if (DWARF2_VERSION < 4)
+ 	    {
+-	      if (exp.X_op == O_constant)
+-		exp.X_op = O_symbol;
+-	      exp.X_add_symbol = symp;
+-	      emit_expr (&exp, sizeof_address);
++	      if (size.X_op == O_constant)
++		size.X_op = O_symbol;
++	      size.X_add_symbol = symp;
++	      emit_expr (&size, sizeof_address);
+ 	    }
+-	  else if (exp.X_op == O_constant)
+-	    out_uleb128 (exp.X_add_number);
++	  else if (size.X_op == O_constant)
++	    out_uleb128 (size.X_add_number);
+ 	  else
+-	    emit_leb128_expr (symbol_get_value_expression (exp.X_op_symbol), 0);
++	    emit_leb128_expr (symbol_get_value_expression (size.X_op_symbol), 0);
+ 	}
+ 
+       /* End of children.  */
diff --git a/toolchain/binutils/patches/2.39/009-PR29462-internal-error-in-relocate-at-powerpc.cc-107.patch b/toolchain/binutils/patches/2.39/009-PR29462-internal-error-in-relocate-at-powerpc.cc-107.patch
new file mode 100644
index 0000000000..e325d3bcb0
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/009-PR29462-internal-error-in-relocate-at-powerpc.cc-107.patch
@@ -0,0 +1,270 @@
+From e3b5d935247084dca057dea72be61b063fe2357a Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Wed, 10 Aug 2022 10:38:52 +0930
+Subject: [PATCH 009/160] PR29462, internal error in relocate, at
+ powerpc.cc:10796
+
+Prior to the inline plt call support (commit 08be322439), the only
+local syms with plt entries were local ifunc symbols.  There shouldn't
+be stubs for other local symbols so don't look for them.  The patch
+also fixes minor bugs in get_reference_flags; Many relocs are valid
+only for ppc64 and a couple only for ppc32.
+
+	PR 29462
+	* powerpc.cc (Target_powerpc::Relocate::relocate): Rename
+	use_plt_offset to pltcal_to_direct, invert logic.  For relocs
+	not used with inline plt sequences against local symbols, only
+	look for stubs when the symbol is an ifunc.
+	(Target_powerpc::Scan::get_reference_flags): Correct reloc
+	handling for relocs not valid for both 32-bit and 64-bit.
+
+(cherry picked from commit 6158b25f77db11712b84e6a4609898f2615ac749)
+---
+ gold/powerpc.cc | 129 ++++++++++++++++++++++++++++--------------------
+ 1 file changed, 75 insertions(+), 54 deletions(-)
+
+--- a/gold/powerpc.cc
++++ b/gold/powerpc.cc
+@@ -7675,22 +7675,18 @@ Target_powerpc<size, big_endian>::Scan::
+ 
+   switch (r_type)
+     {
++    case elfcpp::R_PPC64_TOC:
++      if (size != 64)
++	break;
++      // Fall through.
+     case elfcpp::R_POWERPC_NONE:
+     case elfcpp::R_POWERPC_GNU_VTINHERIT:
+     case elfcpp::R_POWERPC_GNU_VTENTRY:
+-    case elfcpp::R_PPC64_TOC:
+       // No symbol reference.
+       break;
+ 
+     case elfcpp::R_PPC64_ADDR64:
+     case elfcpp::R_PPC64_UADDR64:
+-    case elfcpp::R_POWERPC_ADDR32:
+-    case elfcpp::R_POWERPC_UADDR32:
+-    case elfcpp::R_POWERPC_ADDR16:
+-    case elfcpp::R_POWERPC_UADDR16:
+-    case elfcpp::R_POWERPC_ADDR16_LO:
+-    case elfcpp::R_POWERPC_ADDR16_HI:
+-    case elfcpp::R_POWERPC_ADDR16_HA:
+     case elfcpp::R_PPC64_ADDR16_HIGHER34:
+     case elfcpp::R_PPC64_ADDR16_HIGHERA34:
+     case elfcpp::R_PPC64_ADDR16_HIGHEST34:
+@@ -7700,6 +7696,16 @@ Target_powerpc<size, big_endian>::Scan::
+     case elfcpp::R_PPC64_D34_HI30:
+     case elfcpp::R_PPC64_D34_HA30:
+     case elfcpp::R_PPC64_D28:
++      if (size != 64)
++	break;
++      // Fall through.
++    case elfcpp::R_POWERPC_ADDR32:
++    case elfcpp::R_POWERPC_UADDR32:
++    case elfcpp::R_POWERPC_ADDR16:
++    case elfcpp::R_POWERPC_UADDR16:
++    case elfcpp::R_POWERPC_ADDR16_LO:
++    case elfcpp::R_POWERPC_ADDR16_HI:
++    case elfcpp::R_POWERPC_ADDR16_HA:
+       ref = Symbol::ABSOLUTE_REF;
+       break;
+ 
+@@ -7710,13 +7716,14 @@ Target_powerpc<size, big_endian>::Scan::
+       ref = Symbol::FUNCTION_CALL | Symbol::ABSOLUTE_REF;
+       break;
+ 
+-    case elfcpp::R_PPC64_REL64:
+-    case elfcpp::R_POWERPC_REL32:
+     case elfcpp::R_PPC_LOCAL24PC:
+-    case elfcpp::R_POWERPC_REL16:
+-    case elfcpp::R_POWERPC_REL16_LO:
+-    case elfcpp::R_POWERPC_REL16_HI:
+-    case elfcpp::R_POWERPC_REL16_HA:
++      if (size != 32)
++	break;
++      // Fall through.
++      ref = Symbol::RELATIVE_REF;
++      break;
++
++    case elfcpp::R_PPC64_REL64:
+     case elfcpp::R_PPC64_REL16_HIGH:
+     case elfcpp::R_PPC64_REL16_HIGHA:
+     case elfcpp::R_PPC64_REL16_HIGHER:
+@@ -7729,36 +7736,45 @@ Target_powerpc<size, big_endian>::Scan::
+     case elfcpp::R_PPC64_REL16_HIGHEST34:
+     case elfcpp::R_PPC64_REL16_HIGHESTA34:
+     case elfcpp::R_PPC64_PCREL28:
++      if (size != 64)
++	break;
++      // Fall through.
++    case elfcpp::R_POWERPC_REL32:
++    case elfcpp::R_POWERPC_REL16:
++    case elfcpp::R_POWERPC_REL16_LO:
++    case elfcpp::R_POWERPC_REL16_HI:
++    case elfcpp::R_POWERPC_REL16_HA:
+       ref = Symbol::RELATIVE_REF;
+       break;
+ 
++    case elfcpp::R_PPC_PLTREL24:
++      if (size != 32)
++	break;
++      ref = Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
++      break;
++
+     case elfcpp::R_PPC64_REL24_NOTOC:
+-      if (size == 32)
++    case elfcpp::R_PPC64_REL24_P9NOTOC:
++    case elfcpp::R_PPC64_PLT16_LO_DS:
++    case elfcpp::R_PPC64_PLTSEQ_NOTOC:
++    case elfcpp::R_PPC64_PLTCALL_NOTOC:
++    case elfcpp::R_PPC64_PLT_PCREL34:
++    case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
++      if (size != 64)
+ 	break;
+       // Fall through.
+-    case elfcpp::R_PPC64_REL24_P9NOTOC:
+     case elfcpp::R_POWERPC_REL24:
+-    case elfcpp::R_PPC_PLTREL24:
+     case elfcpp::R_POWERPC_REL14:
+     case elfcpp::R_POWERPC_REL14_BRTAKEN:
+     case elfcpp::R_POWERPC_REL14_BRNTAKEN:
+     case elfcpp::R_POWERPC_PLT16_LO:
+     case elfcpp::R_POWERPC_PLT16_HI:
+     case elfcpp::R_POWERPC_PLT16_HA:
+-    case elfcpp::R_PPC64_PLT16_LO_DS:
+     case elfcpp::R_POWERPC_PLTSEQ:
+-    case elfcpp::R_PPC64_PLTSEQ_NOTOC:
+     case elfcpp::R_POWERPC_PLTCALL:
+-    case elfcpp::R_PPC64_PLTCALL_NOTOC:
+-    case elfcpp::R_PPC64_PLT_PCREL34:
+-    case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
+       ref = Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
+       break;
+ 
+-    case elfcpp::R_POWERPC_GOT16:
+-    case elfcpp::R_POWERPC_GOT16_LO:
+-    case elfcpp::R_POWERPC_GOT16_HI:
+-    case elfcpp::R_POWERPC_GOT16_HA:
+     case elfcpp::R_PPC64_GOT16_DS:
+     case elfcpp::R_PPC64_GOT16_LO_DS:
+     case elfcpp::R_PPC64_GOT_PCREL34:
+@@ -7768,11 +7784,16 @@ Target_powerpc<size, big_endian>::Scan::
+     case elfcpp::R_PPC64_TOC16_HA:
+     case elfcpp::R_PPC64_TOC16_DS:
+     case elfcpp::R_PPC64_TOC16_LO_DS:
++      if (size != 64)
++	break;
++      // Fall through.
++    case elfcpp::R_POWERPC_GOT16:
++    case elfcpp::R_POWERPC_GOT16_LO:
++    case elfcpp::R_POWERPC_GOT16_HI:
++    case elfcpp::R_POWERPC_GOT16_HA:
+       ref = Symbol::RELATIVE_REF;
+       break;
+ 
+-    case elfcpp::R_POWERPC_GOT_TPREL16:
+-    case elfcpp::R_POWERPC_TLS:
+     case elfcpp::R_PPC64_TLSGD:
+     case elfcpp::R_PPC64_TLSLD:
+     case elfcpp::R_PPC64_TPREL34:
+@@ -7781,6 +7802,11 @@ Target_powerpc<size, big_endian>::Scan::
+     case elfcpp::R_PPC64_GOT_TLSLD_PCREL34:
+     case elfcpp::R_PPC64_GOT_TPREL_PCREL34:
+     case elfcpp::R_PPC64_GOT_DTPREL_PCREL34:
++      if (size != 64)
++	break;
++      // Fall through.
++    case elfcpp::R_POWERPC_GOT_TPREL16:
++    case elfcpp::R_POWERPC_TLS:
+       ref = Symbol::TLS_REF;
+       break;
+ 
+@@ -10671,10 +10697,8 @@ Target_powerpc<size, big_endian>::Reloca
+   bool has_stub_value = false;
+   bool localentry0 = false;
+   unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+-  bool use_plt_offset
+-    = (gsym != NULL
+-       ? gsym->use_plt_offset(Scan::get_reference_flags(r_type, target))
+-       : object->local_has_plt_offset(r_sym));
++  bool pltcall_to_direct = false;
++
+   if (is_plt16_reloc<size>(r_type)
+       || r_type == elfcpp::R_PPC64_PLT_PCREL34
+       || r_type == elfcpp::R_PPC64_PLT_PCREL34_NOTOC
+@@ -10688,21 +10712,18 @@ Target_powerpc<size, big_endian>::Reloca
+       // that the decision depends on the PLTCALL reloc, and we don't
+       // know the address of that instruction when processing others
+       // in the sequence.  So the decision needs to be made in
+-      // do_relax().  For now, don't optimise inline plt calls.
+-      if (gsym)
+-	use_plt_offset = gsym->has_plt_offset();
+-    }
+-  if (use_plt_offset
+-      && !is_got_reloc(r_type)
+-      && !is_plt16_reloc<size>(r_type)
+-      && r_type != elfcpp::R_PPC64_PLT_PCREL34
+-      && r_type != elfcpp::R_PPC64_PLT_PCREL34_NOTOC
+-      && r_type != elfcpp::R_POWERPC_PLTSEQ
+-      && r_type != elfcpp::R_POWERPC_PLTCALL
+-      && r_type != elfcpp::R_PPC64_PLTSEQ_NOTOC
+-      && r_type != elfcpp::R_PPC64_PLTCALL_NOTOC
+-      && (!psymval->is_ifunc_symbol()
+-	  || Scan::reloc_needs_plt_for_ifunc(target, object, r_type, false)))
++      // do_relax().
++      pltcall_to_direct = !(gsym != NULL
++			    ? gsym->has_plt_offset()
++			    : object->local_has_plt_offset(r_sym));
++    }
++  else if ((gsym != NULL
++	    ? gsym->use_plt_offset(Scan::get_reference_flags(r_type, target))
++	    : psymval->is_ifunc_symbol() && object->local_has_plt_offset(r_sym))
++	   && !is_got_reloc(r_type)
++	   && (!psymval->is_ifunc_symbol()
++	       || Scan::reloc_needs_plt_for_ifunc(target, object, r_type,
++						  false)))
+     {
+       if (size == 64
+ 	  && gsym != NULL
+@@ -10796,9 +10817,9 @@ Target_powerpc<size, big_endian>::Reloca
+       gold_assert(has_stub_value || !(os->flags() & elfcpp::SHF_ALLOC));
+     }
+ 
+-  if (use_plt_offset && (is_plt16_reloc<size>(r_type)
+-			 || r_type == elfcpp::R_PPC64_PLT_PCREL34
+-			 || r_type == elfcpp::R_PPC64_PLT_PCREL34_NOTOC))
++  if (!pltcall_to_direct && (is_plt16_reloc<size>(r_type)
++			     || r_type == elfcpp::R_PPC64_PLT_PCREL34
++			     || r_type == elfcpp::R_PPC64_PLT_PCREL34_NOTOC))
+     {
+       const Output_data_plt_powerpc<size, big_endian>* plt;
+       if (gsym)
+@@ -10826,7 +10847,7 @@ Target_powerpc<size, big_endian>::Reloca
+ 	    value -= target->toc_pointer();
+ 	}
+     }
+-  else if (!use_plt_offset
++  else if (pltcall_to_direct
+ 	   && (is_plt16_reloc<size>(r_type)
+ 	       || r_type == elfcpp::R_POWERPC_PLTSEQ
+ 	       || r_type == elfcpp::R_PPC64_PLTSEQ_NOTOC))
+@@ -10835,7 +10856,7 @@ Target_powerpc<size, big_endian>::Reloca
+       elfcpp::Swap<32, big_endian>::writeval(iview, nop);
+       r_type = elfcpp::R_POWERPC_NONE;
+     }
+-  else if (!use_plt_offset
++  else if (pltcall_to_direct
+ 	   && (r_type == elfcpp::R_PPC64_PLT_PCREL34
+ 	       || r_type == elfcpp::R_PPC64_PLT_PCREL34_NOTOC))
+     {
+@@ -11316,8 +11337,8 @@ Target_powerpc<size, big_endian>::Reloca
+     }
+   else if (!has_stub_value)
+     {
+-      if (!use_plt_offset && (r_type == elfcpp::R_POWERPC_PLTCALL
+-			      || r_type == elfcpp::R_PPC64_PLTCALL_NOTOC))
++      if (pltcall_to_direct && (r_type == elfcpp::R_POWERPC_PLTCALL
++				|| r_type == elfcpp::R_PPC64_PLTCALL_NOTOC))
+ 	{
+ 	  // PLTCALL without plt entry => convert to direct call
+ 	  Insn* iview = reinterpret_cast<Insn*>(view);
diff --git a/toolchain/binutils/patches/2.39/011-PR29466-APP-NO_APP-with-.linefile.patch b/toolchain/binutils/patches/2.39/011-PR29466-APP-NO_APP-with-.linefile.patch
new file mode 100644
index 0000000000..f7b5819929
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/011-PR29466-APP-NO_APP-with-.linefile.patch
@@ -0,0 +1,167 @@
+From 9e855cffa1fda44629e7f9b76dfa3e5a51a440e9 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Thu, 11 Aug 2022 09:51:03 +0930
+Subject: [PATCH 011/160] PR29466, APP/NO_APP with .linefile
+
+Commit 53f2b36a54b9 exposed a bug in sb_scrub_and_add_sb that could
+result in losing input.  If scrubbing results in expansion past the
+holding capacity of do_scrub_chars output buffer, then do_scrub_chars
+stashes the extra input for the next call.  That call never came
+because sb_scrub_and_add_sb wrongly decided it was done.  Fix that by
+allowing sb_scrub_and_add_sb to see whether there is pending input.
+Also allow a little extra space so that in most cases we won't need
+to resize the output buffer.
+
+sb_scrub_and_add_sb also limited output to the size of the input,
+rather than the actual output buffer size.  Fixing that resulted in a
+fail of gas/testsuite/macros/dot with an extra warning: "end of file
+not at end of a line; newline inserted".  OK, so the macro in dot.s
+really does finish without end-of-line.  Apparently the macro
+expansion code relied on do_scrub_chars returning early.  So fix that
+too by adding a newline if needed in macro_expand_body.
+
+	PR 29466
+	* app.c (do_scrub_pending): New function.
+	* as.h: Declare it.
+	* input-scrub.c (input_scrub_include_sb): Add extra space for
+	two .linefile directives.
+	* sb.c (sb_scrub_and_add_sb): Take into account pending input.
+	Allow output to max.
+	* macro.c (macro_expand_body): Add terminating newline.
+	* testsuite/config/default.exp (SIZE, SIZEFLAGS): Define.
+	* testsuite/gas/macros/app5.d,
+	* testsuite/gas/macros/app5.s: New test.
+	* testsuite/gas/macros/macros.exp: Run it.
+
+(cherry picked from commit 4d74aab7aa562fe79d4669cdad0c32610531cbc0)
+---
+ gas/app.c                           | 13 +++++++++++++
+ gas/as.h                            |  1 +
+ gas/input-scrub.c                   |  6 ++++--
+ gas/macro.c                         |  2 ++
+ gas/sb.c                            |  5 +++--
+ gas/testsuite/config/default.exp    |  8 ++++++++
+ gas/testsuite/gas/macros/app5.d     |  6 ++++++
+ gas/testsuite/gas/macros/app5.s     |  5 +++++
+ gas/testsuite/gas/macros/macros.exp |  1 +
+ 9 files changed, 43 insertions(+), 4 deletions(-)
+ create mode 100644 gas/testsuite/gas/macros/app5.d
+ create mode 100644 gas/testsuite/gas/macros/app5.s
+
+--- a/gas/app.c
++++ b/gas/app.c
+@@ -1537,3 +1537,16 @@ do_scrub_chars (size_t (*get) (char *, s
+     last_char = to[-1];
+   return to - tostart;
+ }
++
++/* Return amount of pending input.  */
++
++size_t
++do_scrub_pending (void)
++{
++  size_t len = 0;
++  if (saved_input)
++    len += saved_input_len;
++  if (state == -1)
++    len += strlen (out_string);
++  return len;
++}
+--- a/gas/as.h
++++ b/gas/as.h
+@@ -460,6 +460,7 @@ void   input_scrub_insert_file (char *);
+ char * input_scrub_new_file (const char *);
+ char * input_scrub_next_buffer (char **bufp);
+ size_t do_scrub_chars (size_t (*get) (char *, size_t), char *, size_t);
++size_t do_scrub_pending (void);
+ bool   scan_for_multibyte_characters (const unsigned char *, const unsigned char *, bool);
+ int    gen_to_words (LITTLENUM_TYPE *, int, long);
+ int    had_err (void);
+--- a/gas/input-scrub.c
++++ b/gas/input-scrub.c
+@@ -278,9 +278,11 @@ input_scrub_include_sb (sb *from, char *
+ 
+   next_saved_file = input_scrub_push (position);
+ 
+-  /* Allocate sufficient space: from->len + optional newline.  */
++  /* Allocate sufficient space: from->len plus optional newline
++     plus two ".linefile " directives, plus a little more for other
++     expansion.  */
+   newline = from->len >= 1 && from->ptr[0] != '\n';
+-  sb_build (&from_sb, from->len + newline);
++  sb_build (&from_sb, from->len + newline + 2 * sizeof (".linefile") + 30);
+   if (expansion == expanding_repeat && from_sb_expansion >= expanding_macro)
+     expansion = expanding_nested;
+   from_sb_expansion = expansion;
+--- a/gas/macro.c
++++ b/gas/macro.c
+@@ -1056,6 +1056,8 @@ macro_expand_body (sb *in, sb *out, form
+       loclist = f;
+     }
+ 
++  if (!err && (out->len == 0 || out->ptr[out->len - 1] != '\n'))
++    sb_add_char (out, '\n');
+   return err;
+ }
+ 
+--- a/gas/sb.c
++++ b/gas/sb.c
+@@ -119,11 +119,12 @@ sb_scrub_and_add_sb (sb *ptr, sb *s)
+      So we loop until the input S is consumed.  */
+   while (1)
+     {
+-      size_t copy = s->len - (scrub_position - s->ptr);
++      size_t copy = s->len - (scrub_position - s->ptr) + do_scrub_pending ();
+       if (copy == 0)
+ 	break;
+       sb_check (ptr, copy);
+-      ptr->len += do_scrub_chars (scrub_from_sb, ptr->ptr + ptr->len, copy);
++      ptr->len += do_scrub_chars (scrub_from_sb, ptr->ptr + ptr->len,
++				  ptr->max - ptr->len);
+     }
+ 
+   sb_to_scrub = 0;
+--- a/gas/testsuite/config/default.exp
++++ b/gas/testsuite/config/default.exp
+@@ -52,6 +52,14 @@ if ![info exists NMFLAGS] then {
+     set NMFLAGS {}
+ }
+ 
++if ![info exists SIZE] then {
++    set SIZE [findfile $base_dir/size]
++}
++
++if ![info exists SIZEFLAGS] then {
++    set SIZEFLAGS ""
++}
++
+ if ![info exists OBJCOPY] then {
+     set OBJCOPY [findfile $base_dir/../../binutils/objcopy]
+ }
+--- /dev/null
++++ b/gas/testsuite/gas/macros/app5.d
+@@ -0,0 +1,6 @@
++#name: APP with linefile
++#xfail: tic30-*-*
++#size: -G
++# pr29466 just check that the test assembles
++
++#pass
+--- /dev/null
++++ b/gas/testsuite/gas/macros/app5.s
+@@ -0,0 +1,5 @@
++#NO_APP
++#APP
++# 5 "foo.c" 1
++# 0 "" 2
++#NO_APP
+--- a/gas/testsuite/gas/macros/macros.exp
++++ b/gas/testsuite/gas/macros/macros.exp
+@@ -70,6 +70,7 @@ run_dump_test app2
+ run_dump_test app3
+ remote_download host "$srcdir/$subdir/app4b.s"
+ run_dump_test app4
++run_dump_test app5
+ 
+ run_list_test badarg ""
+ 
diff --git a/toolchain/binutils/patches/2.39/039-LoongArch-ld-Fix-relocation-error-of-pcrel.patch b/toolchain/binutils/patches/2.39/039-LoongArch-ld-Fix-relocation-error-of-pcrel.patch
new file mode 100644
index 0000000000..67e499de67
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/039-LoongArch-ld-Fix-relocation-error-of-pcrel.patch
@@ -0,0 +1,128 @@
+From 509a2ec6ad3ea7eb3f4cf59538cf636a2126e4c3 Mon Sep 17 00:00:00 2001
+From: liuzhensong <liuzhensong at loongson.cn>
+Date: Fri, 2 Sep 2022 16:29:14 +0800
+Subject: [PATCH 039/160] LoongArch:ld: Fix relocation error of pcrel.
+
+  Patch for branch 2.39.
+  Need to reduce the address of pc when using
+  reloction R_LARCH_SOP_PUSH_PCREL.
+
+  bfd/
+    * elfnn-loongarch.c
+---
+ bfd/elfnn-loongarch.c                         |  3 +-
+ ld/testsuite/ld-loongarch-elf/pcrel-const.d   | 14 +++++++
+ ld/testsuite/ld-loongarch-elf/pcrel-const.lds | 14 +++++++
+ ld/testsuite/ld-loongarch-elf/pcrel-const.s   | 12 ++++++
+ ld/testsuite/ld-loongarch-elf/pr.exp          | 39 +++++++++++++++++++
+ 5 files changed, 81 insertions(+), 1 deletion(-)
+ create mode 100644 ld/testsuite/ld-loongarch-elf/pcrel-const.d
+ create mode 100644 ld/testsuite/ld-loongarch-elf/pcrel-const.lds
+ create mode 100644 ld/testsuite/ld-loongarch-elf/pcrel-const.s
+ create mode 100644 ld/testsuite/ld-loongarch-elf/pr.exp
+
+--- a/bfd/elfnn-loongarch.c
++++ b/bfd/elfnn-loongarch.c
+@@ -2341,9 +2341,10 @@ loongarch_elf_relocate_section (bfd *out
+ 	case R_LARCH_SOP_PUSH_PLT_PCREL:
+ 	  unresolved_reloc = false;
+ 
+-	  if (resolved_to_const)
++	  if (!is_undefweak && resolved_to_const)
+ 	    {
+ 	      relocation += rel->r_addend;
++	      relocation -= pc;
+ 	      break;
+ 	    }
+ 	  else if (is_undefweak)
+--- /dev/null
++++ b/ld/testsuite/ld-loongarch-elf/pcrel-const.d
+@@ -0,0 +1,14 @@
++#as: -mla-global-with-pcrel
++#objdump: -Drsz
++
++.*:[    ]+file format .*
++
++
++Disassembly of section .text:
++
++.* <foo>:
++#...
++[ 	]+8:[ 	]+02c04084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+16\(0x10\)
++#...
++0+14 <__sec_end>:
++#pass
+--- /dev/null
++++ b/ld/testsuite/ld-loongarch-elf/pcrel-const.lds
+@@ -0,0 +1,14 @@
++ENTRY(foo);
++SECTIONS
++{
++	.text : {
++		*(.text*)
++	}
++
++	.data : {
++		__sec_start = .;
++		*(.gzdata)
++		__sec_end = .;
++	}
++}
++PROVIDE(__sec_size = __sec_end);
+--- /dev/null
++++ b/ld/testsuite/ld-loongarch-elf/pcrel-const.s
+@@ -0,0 +1,12 @@
++	.text
++	.align	2
++	.globl	foo
++	.type	foo, @function
++foo:
++	nop
++	la.global	$r4,__sec_size
++	ldptr.w	$r4,$r4,0
++	jr	$r1
++	.size	foo, .-foo
++	.data
++	.word 1
+--- /dev/null
++++ b/ld/testsuite/ld-loongarch-elf/pr.exp
+@@ -0,0 +1,39 @@
++# Expect script for LoongArch ELF linker tests
++#   Copyright (C) 2022 Free Software Foundation, Inc.
++#
++# This file is part of the GNU Binutils.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
++# MA 02110-1301, USA.
++#
++
++if ![istarget loongarch64-*-*] {
++  return
++}
++
++set link_tests [list \
++  [list \
++    "pcrel const" \
++    "-T pcrel-const.lds" "" \
++    "-mla-global-with-pcrel" \
++    { pcrel-const.s } \
++    [list \
++      [list objdump -D pcrel-const.d] \
++    ] \
++    "pcrel-const" \
++  ] \
++]
++
++run_ld_link_tests $link_tests
diff --git a/toolchain/binutils/patches/2.39/043-Re-PR29466-APP-NO_APP-with-linefile.patch b/toolchain/binutils/patches/2.39/043-Re-PR29466-APP-NO_APP-with-linefile.patch
new file mode 100644
index 0000000000..1de501a1ae
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/043-Re-PR29466-APP-NO_APP-with-linefile.patch
@@ -0,0 +1,27 @@
+From 4233be14a34d754a70b8b6f6fa42d21f35c6e030 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Sat, 10 Sep 2022 07:30:57 +0930
+Subject: [PATCH 043/160] Re: PR29466, APP/NO_APP with linefile
+
+It looks like I copied the SIZE init across from
+binutils/testsuite/config/default.exp without some necessary editing.
+
+	PR 29466
+	* testsuite/config/default.exp (SIZE): Adjust relative path.
+
+(cherry picked from commit 1180f540d5f2f7751b5309bdd6c38d69fcf699e7)
+---
+ gas/testsuite/config/default.exp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/gas/testsuite/config/default.exp
++++ b/gas/testsuite/config/default.exp
+@@ -53,7 +53,7 @@ if ![info exists NMFLAGS] then {
+ }
+ 
+ if ![info exists SIZE] then {
+-    set SIZE [findfile $base_dir/size]
++    set SIZE [findfile $base_dir/../../binutils/size]
+ }
+ 
+ if ![info exists SIZEFLAGS] then {
diff --git a/toolchain/binutils/patches/2.39/050-PowerPC64-pcrel-got-relocs-against-local-symbols.patch b/toolchain/binutils/patches/2.39/050-PowerPC64-pcrel-got-relocs-against-local-symbols.patch
new file mode 100644
index 0000000000..5c89f6804e
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/050-PowerPC64-pcrel-got-relocs-against-local-symbols.patch
@@ -0,0 +1,38 @@
+From 4d7bba23a39fba18d6d13a2941a3c232011a7064 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Fri, 16 Sep 2022 18:08:44 +0930
+Subject: [PATCH 050/160] PowerPC64 pcrel got relocs against local symbols
+
+Not that anyone would want to indirect via the GOT when an address can
+be loaded directly with pla, the following:
+
+ pld 3,x at got@pcrel
+x:
+
+leads to "Internal error in md_apply_fix", because the generic parts
+of assembler fixup handling convert the fx_pcrel fixup to one without
+a symbol.  Stop that happening.
+
+	* config/tc-ppc.c (ppc_force_relocation): Add PLT_PCREL34 and
+	assorted GOT_PCREL34 relocs.
+
+(cherry picked from commit 49c3ed081fed6b8e2b48fdc48f805f11e4589514)
+---
+ gas/config/tc-ppc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/gas/config/tc-ppc.c
++++ b/gas/config/tc-ppc.c
+@@ -6676,6 +6676,12 @@ ppc_force_relocation (fixS *fix)
+     case BFD_RELOC_PPC_BA16_BRNTAKEN:
+     case BFD_RELOC_24_PLT_PCREL:
+     case BFD_RELOC_PPC64_TOC:
++    case BFD_RELOC_PPC64_PLT_PCREL34:
++    case BFD_RELOC_PPC64_GOT_PCREL34:
++    case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34:
++    case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34:
++    case BFD_RELOC_PPC64_GOT_TPREL_PCREL34:
++    case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34:
+       return 1;
+     case BFD_RELOC_PPC_B26:
+     case BFD_RELOC_PPC_BA26:
diff --git a/toolchain/binutils/patches/2.39/055-Re-PowerPC64-pcrel-got-relocs-against-local-symbols.patch b/toolchain/binutils/patches/2.39/055-Re-PowerPC64-pcrel-got-relocs-against-local-symbols.patch
new file mode 100644
index 0000000000..19b80c3442
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/055-Re-PowerPC64-pcrel-got-relocs-against-local-symbols.patch
@@ -0,0 +1,94 @@
+From 010db38b54b589ca3e95b498aba2831064970171 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Wed, 21 Sep 2022 09:06:29 +0930
+Subject: [PATCH 055/160] Re: PowerPC64 pcrel got relocs against local symbols
+
+The last patch wasn't all that shiny.  There are rather a lot more
+relocations that can hit the assertion in md_apply_fix if the symbol
+is local or absolute.  Fix them all.
+
+	* config/tc-ppc.c (ppc_force_relocation): Add all relocs that
+	expect a symbol in md_apply_fix.  Remove tls pcrel relocs
+	already covered in general tls match range.
+
+(cherry picked from commit 8b168f1a1e09e337d2a970f204a0230c091bbe58)
+---
+ gas/config/tc-ppc.c | 58 ++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 52 insertions(+), 6 deletions(-)
+
+--- a/gas/config/tc-ppc.c
++++ b/gas/config/tc-ppc.c
+@@ -6666,8 +6666,6 @@ ppc_force_relocation (fixS *fix)
+ int
+ ppc_force_relocation (fixS *fix)
+ {
+-  /* Branch prediction relocations must force a relocation, as must
+-     the vtable description relocs.  */
+   switch (fix->fx_r_type)
+     {
+     case BFD_RELOC_PPC_B16_BRTAKEN:
+@@ -6676,12 +6674,60 @@ ppc_force_relocation (fixS *fix)
+     case BFD_RELOC_PPC_BA16_BRNTAKEN:
+     case BFD_RELOC_24_PLT_PCREL:
+     case BFD_RELOC_PPC64_TOC:
++    case BFD_RELOC_16_GOTOFF:
++    case BFD_RELOC_LO16_GOTOFF:
++    case BFD_RELOC_HI16_GOTOFF:
++    case BFD_RELOC_HI16_S_GOTOFF:
++    case BFD_RELOC_LO16_PLTOFF:
++    case BFD_RELOC_HI16_PLTOFF:
++    case BFD_RELOC_HI16_S_PLTOFF:
++    case BFD_RELOC_GPREL16:
++    case BFD_RELOC_16_BASEREL:
++    case BFD_RELOC_LO16_BASEREL:
++    case BFD_RELOC_HI16_BASEREL:
++    case BFD_RELOC_HI16_S_BASEREL:
++    case BFD_RELOC_PPC_TOC16:
++    case BFD_RELOC_PPC64_TOC16_LO:
++    case BFD_RELOC_PPC64_TOC16_HI:
++    case BFD_RELOC_PPC64_TOC16_HA:
++    case BFD_RELOC_PPC64_PLTGOT16:
++    case BFD_RELOC_PPC64_PLTGOT16_LO:
++    case BFD_RELOC_PPC64_PLTGOT16_HI:
++    case BFD_RELOC_PPC64_PLTGOT16_HA:
++    case BFD_RELOC_PPC64_GOT16_DS:
++    case BFD_RELOC_PPC64_GOT16_LO_DS:
++    case BFD_RELOC_PPC64_PLT16_LO_DS:
++    case BFD_RELOC_PPC64_SECTOFF_DS:
++    case BFD_RELOC_PPC64_SECTOFF_LO_DS:
++    case BFD_RELOC_PPC64_TOC16_DS:
++    case BFD_RELOC_PPC64_TOC16_LO_DS:
++    case BFD_RELOC_PPC64_PLTGOT16_DS:
++    case BFD_RELOC_PPC64_PLTGOT16_LO_DS:
++    case BFD_RELOC_PPC_EMB_NADDR16:
++    case BFD_RELOC_PPC_EMB_NADDR16_LO:
++    case BFD_RELOC_PPC_EMB_NADDR16_HI:
++    case BFD_RELOC_PPC_EMB_NADDR16_HA:
++    case BFD_RELOC_PPC_EMB_SDAI16:
++    case BFD_RELOC_PPC_EMB_SDA2I16:
++    case BFD_RELOC_PPC_EMB_SDA2REL:
++    case BFD_RELOC_PPC_EMB_SDA21:
++    case BFD_RELOC_PPC_EMB_MRKREF:
++    case BFD_RELOC_PPC_EMB_RELSEC16:
++    case BFD_RELOC_PPC_EMB_RELST_LO:
++    case BFD_RELOC_PPC_EMB_RELST_HI:
++    case BFD_RELOC_PPC_EMB_RELST_HA:
++    case BFD_RELOC_PPC_EMB_BIT_FLD:
++    case BFD_RELOC_PPC_EMB_RELSDA:
++    case BFD_RELOC_PPC_VLE_SDA21:
++    case BFD_RELOC_PPC_VLE_SDA21_LO:
++    case BFD_RELOC_PPC_VLE_SDAREL_LO16A:
++    case BFD_RELOC_PPC_VLE_SDAREL_LO16D:
++    case BFD_RELOC_PPC_VLE_SDAREL_HI16A:
++    case BFD_RELOC_PPC_VLE_SDAREL_HI16D:
++    case BFD_RELOC_PPC_VLE_SDAREL_HA16A:
++    case BFD_RELOC_PPC_VLE_SDAREL_HA16D:
+     case BFD_RELOC_PPC64_PLT_PCREL34:
+     case BFD_RELOC_PPC64_GOT_PCREL34:
+-    case BFD_RELOC_PPC64_GOT_TLSGD_PCREL34:
+-    case BFD_RELOC_PPC64_GOT_TLSLD_PCREL34:
+-    case BFD_RELOC_PPC64_GOT_TPREL_PCREL34:
+-    case BFD_RELOC_PPC64_GOT_DTPREL_PCREL34:
+       return 1;
+     case BFD_RELOC_PPC_B26:
+     case BFD_RELOC_PPC_BA26:
diff --git a/toolchain/binutils/patches/2.39/058-elf-Reset-alignment-for-each-PT_LOAD-segment.patch b/toolchain/binutils/patches/2.39/058-elf-Reset-alignment-for-each-PT_LOAD-segment.patch
new file mode 100644
index 0000000000..aaf7a1b053
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/058-elf-Reset-alignment-for-each-PT_LOAD-segment.patch
@@ -0,0 +1,89 @@
+From a98316d5cf970cbc99689797d84c2ea832bcdcbb Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools at gmail.com>
+Date: Mon, 1 Aug 2022 16:02:39 -0700
+Subject: [PATCH 058/160] elf: Reset alignment for each PT_LOAD segment
+
+Reset alignment for each PT_LOAD segment to avoid using alignment from
+the previous PT_LOAD segment.
+
+bfd/
+
+	PR ld/29435
+	* elf.c (assign_file_positions_for_load_sections): Reset
+	alignment for each PT_LOAD segment.
+
+ld/
+
+	PR ld/29435
+	* testsuite/ld-elf/pr29435.d: New file.
+	* testsuite/ld-elf/pr29435.s: Likewise.
+
+(cherry picked from commit 59f214544c50ec7ebbca285ff2b4949f48671690)
+---
+ bfd/elf.c                     |  7 ++++---
+ ld/testsuite/ld-elf/pr29435.d | 11 +++++++++++
+ ld/testsuite/ld-elf/pr29435.s |  6 ++++++
+ 3 files changed, 21 insertions(+), 3 deletions(-)
+ create mode 100644 ld/testsuite/ld-elf/pr29435.d
+ create mode 100644 ld/testsuite/ld-elf/pr29435.s
+
+--- a/bfd/elf.c
++++ b/bfd/elf.c
+@@ -5438,8 +5438,6 @@ assign_file_positions_for_load_sections
+   Elf_Internal_Phdr *p;
+   file_ptr off;  /* Octets.  */
+   bfd_size_type maxpagesize;
+-  bfd_size_type p_align;
+-  bool p_align_p = false;
+   unsigned int alloc, actual;
+   unsigned int i, j;
+   struct elf_segment_map **sorted_seg_map;
+@@ -5524,7 +5522,6 @@ assign_file_positions_for_load_sections
+     qsort (sorted_seg_map, alloc, sizeof (*sorted_seg_map),
+ 	   elf_sort_segments);
+ 
+-  p_align = bed->p_align;
+   maxpagesize = 1;
+   if ((abfd->flags & D_PAGED) != 0)
+     {
+@@ -5559,6 +5556,8 @@ assign_file_positions_for_load_sections
+       asection **secpp;
+       bfd_vma off_adjust;  /* Octets.  */
+       bool no_contents;
++      bfd_size_type p_align;
++      bool p_align_p;
+ 
+       /* An ELF segment (described by Elf_Internal_Phdr) may contain a
+ 	 number of sections with contents contributing to both p_filesz
+@@ -5569,6 +5568,8 @@ assign_file_positions_for_load_sections
+       p = phdrs + m->idx;
+       p->p_type = m->p_type;
+       p->p_flags = m->p_flags;
++      p_align = bed->p_align;
++      p_align_p = false;
+ 
+       if (m->count == 0)
+ 	p->p_vaddr = m->p_vaddr_offset * opb;
+--- /dev/null
++++ b/ld/testsuite/ld-elf/pr29435.d
+@@ -0,0 +1,11 @@
++#ld: -shared -z separate-code -z relro
++#xfail: ![check_shared_lib_support]
++#xfail: ![check_relro_support]
++#readelf: -Wl
++
++#failif
++#...
++ +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ .* 0x8000
++#...
++ +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ .* 0x8000
++#...
+--- /dev/null
++++ b/ld/testsuite/ld-elf/pr29435.s
+@@ -0,0 +1,6 @@
++        .text
++	.balign 0x8000
++	.globl	foo
++	.type	foo, %function
++foo:
++	.byte 0
diff --git a/toolchain/binutils/patches/2.39/063-PR29542-PowerPC-gold-internal-error-in-get_output_vi.patch b/toolchain/binutils/patches/2.39/063-PR29542-PowerPC-gold-internal-error-in-get_output_vi.patch
new file mode 100644
index 0000000000..0d66b7750f
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/063-PR29542-PowerPC-gold-internal-error-in-get_output_vi.patch
@@ -0,0 +1,29 @@
+From 041c22e35de06d22566f4c71e4425c3351215e66 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra at gmail.com>
+Date: Sun, 25 Sep 2022 12:07:36 +0930
+Subject: [PATCH 063/160] PR29542, PowerPC gold internal error in
+ get_output_view,
+
+We were attempting to set a BSS style section contents.
+
+	PR 29542
+	* powerpc.cc (Output_data_plt_powerpc::do_write): Don't set .plt,
+	.iplt or .lplt section contents when position independent.
+
+(cherry picked from commit c21736aed1d4877e090df60362413669dbdc391d)
+---
+ gold/powerpc.cc | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/gold/powerpc.cc
++++ b/gold/powerpc.cc
+@@ -4338,7 +4338,8 @@ template<int size, bool big_endian>
+ void
+ Output_data_plt_powerpc<size, big_endian>::do_write(Output_file* of)
+ {
+-  if (!this->sym_ents_.empty())
++  if (!this->sym_ents_.empty()
++      && !parameters->options().output_is_position_independent())
+     {
+       const section_size_type offset = this->offset();
+       const section_size_type oview_size
diff --git a/toolchain/binutils/patches/2.39/116-arm-Use-DWARF-numbering-convention-for-pseudo-regist.patch b/toolchain/binutils/patches/2.39/116-arm-Use-DWARF-numbering-convention-for-pseudo-regist.patch
new file mode 100644
index 0000000000..82a015ee2b
--- /dev/null
+++ b/toolchain/binutils/patches/2.39/116-arm-Use-DWARF-numbering-convention-for-pseudo-regist.patch
@@ -0,0 +1,301 @@
+From 88ac930a725b8aac8284a2738f03b843f4343dd0 Mon Sep 17 00:00:00 2001
+From: Victor Do Nascimento <Victor.DoNascimento at arm.com>
+Date: Thu, 17 Nov 2022 14:48:37 +0000
+Subject: [PATCH 116/160] arm: Use DWARF numbering convention for
+ pseudo-register representation
+
+The patch, initially submitted to trunk in
+https://sourceware.org/pipermail/binutils/2022-July/122092.html ensures correct
+support for handling .save directives for mixed-register type lists involving
+the ra_auth_code pseudo-register, whereby the support first introduced in 2.39
+(https://sourceware.org/pipermail/binutils/2022-May/120672.html) led to the
+generation of unwinder code popping registers in reversed order.
+
+gas/Changelog:
+
+  * config/tc-arm.c (REG_RA_AUTH_CODE): New.
+  (parse_dot_save): Likewise.
+  (parse_reg_list): Remove obsolete code.
+  (reg_names): Set ra_auth_code to 143.
+  (s_arm_unwind_save): Handle core and pseudo-register lists via
+  parse_dot_save.
+  (s_arm_unwind_save_mixed): Deleted.
+  (s_arm_unwind_save_pseudo): Handle one register at a time.
+  * testsuite/gas/arm/unwind-pacbti-m-readelf.d: Fix test.
+  * testsuite/gas/arm/unwind-pacbti-m.d: Likewise.
+
+(cherry picked from commit 3a368c4c248f6e9f4bda3a5369befa17a4560293)
+---
+ gas/config/tc-arm.c                           | 159 ++++++++++--------
+ .../gas/arm/unwind-pacbti-m-readelf.d         |   4 +-
+ gas/testsuite/gas/arm/unwind-pacbti-m.d       |   2 +-
+ 3 files changed, 95 insertions(+), 70 deletions(-)
+
+--- a/gas/config/tc-arm.c
++++ b/gas/config/tc-arm.c
+@@ -742,6 +742,7 @@ const char * const reg_expected_msgs[] =
+ #define REG_SP	13
+ #define REG_LR	14
+ #define REG_PC	15
++#define REG_RA_AUTH_CODE 143
+ 
+ /* ARM instructions take 4bytes in the object file, Thumb instructions
+    take 2:  */
+@@ -1943,21 +1944,6 @@ parse_reg_list (char ** strp, enum reg_l
+ 
+ 	      reg = arm_reg_parse (&str, rt);
+ 
+-	      /* Skip over allowed registers of alternative types in mixed-type
+-	         register lists.  */
+-	      if (reg == FAIL && rt == REG_TYPE_PSEUDO
+-		  && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
+-		{
+-		  cur_reg = reg;
+-		  continue;
+-		}
+-	      else if (reg == FAIL && rt == REG_TYPE_RN
+-		       && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
+-		{
+-		  cur_reg = reg;
+-		  continue;
+-		}
+-
+ 	      if (etype == REGLIST_CLRM)
+ 		{
+ 		  if (reg == REG_SP || reg == REG_PC)
+@@ -4139,7 +4125,6 @@ s_arm_unwind_fnstart (int ignored ATTRIB
+   unwind.sp_restored = 0;
+ }
+ 
+-
+ /* Parse a handlerdata directive.  Creates the exception handling table entry
+    for the function.  */
+ 
+@@ -4297,15 +4282,19 @@ s_arm_unwind_personality (int ignored AT
+ /* Parse a directive saving pseudo registers.  */
+ 
+ static void
+-s_arm_unwind_save_pseudo (long range)
++s_arm_unwind_save_pseudo (int regno)
+ {
+   valueT op;
+ 
+-  if (range & (1 << 12))
++  switch (regno)
+     {
++    case REG_RA_AUTH_CODE:
+       /* Opcode for restoring RA_AUTH_CODE.  */
+       op = 0xb4;
+       add_unwind_opcode (op, 1);
++      break;
++    default:
++      as_bad (_("Unknown register %d encountered\n"), regno);
+     }
+ }
+ 
+@@ -4375,6 +4364,80 @@ s_arm_unwind_save_core (long range)
+     }
+ }
+ 
++/* Implement correct handling of .save lists enabling the split into
++sublists where necessary, while preserving correct sublist ordering.  */
++
++static void
++parse_dot_save (char **str_p, int prev_reg)
++{
++  long core_regs = 0;
++  int reg;
++  int in_range = 0;
++
++  if (**str_p == ',')
++    *str_p += 1;
++  if (**str_p == '}')
++    {
++      *str_p += 1;
++      return;
++    }
++
++  while ((reg = arm_reg_parse (str_p, REG_TYPE_RN)) != FAIL)
++    {
++      if (!in_range)
++	{
++	  if (core_regs & (1 << reg))
++	    as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
++		       reg);
++	  else if (reg <= prev_reg)
++	    as_tsktsk (_("Warning: register list not in ascending order"));
++
++	  core_regs |= (1 << reg);
++	  prev_reg = reg;
++	  if (skip_past_char(str_p, '-') != FAIL)
++	    in_range = 1;
++	  else if (skip_past_comma(str_p) == FAIL)
++	    first_error (_("bad register list"));
++	}
++      else
++	{
++	  int i;
++	  if (reg <= prev_reg)
++	    first_error (_("bad range in register list"));
++	  for (i = prev_reg + 1; i <= reg; i++)
++	    {
++	      if (core_regs & (1 << i))
++		as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
++			   i);
++	      else
++		core_regs |= 1 << i;
++	    }
++	  in_range = 0;
++	}
++    }
++  if (core_regs)
++    {
++      /* Higher register numbers go in higher memory addresses.  When splitting a list,
++	 right-most sublist should therefore be .saved first.  Use recursion for this.  */
++      parse_dot_save (str_p, reg);
++      /* We're back from recursion, so emit .save insn for sublist.  */
++      s_arm_unwind_save_core (core_regs);
++      return;
++    }
++  /* Handle pseudo-regs, under assumption these are emitted singly.  */
++  else if ((reg = arm_reg_parse (str_p, REG_TYPE_PSEUDO)) != FAIL)
++    {
++      /* Recurse for remainder of input.  Note: No assumption is made regarding which
++	 register in core register set holds pseudo-register.  It's not considered in
++	 ordering check beyond ensuring it's not sandwiched between 2 consecutive
++	 registers.  */
++      parse_dot_save (str_p, prev_reg + 1);
++      s_arm_unwind_save_pseudo (reg);
++      return;
++    }
++  else
++    as_bad (BAD_SYNTAX);
++}
+ 
+ /* Parse a directive saving FPA registers.  */
+ 
+@@ -4716,39 +4779,13 @@ s_arm_unwind_save_mmxwcg (void)
+   ignore_rest_of_line ();
+ }
+ 
+-/* Convert range and mask_range into a sequence of s_arm_unwind_core
+-   and s_arm_unwind_pseudo operations.  We assume that mask_range will
+-   not have consecutive bits set, or that one operation per bit is
+-   acceptable.  */
+-
+-static void
+-s_arm_unwind_save_mixed (long range, long mask_range)
+-{
+-  while (mask_range)
+-    {
+-      long mask_bit = mask_range & -mask_range;
+-      long subrange = range & (mask_bit - 1);
+-
+-      if (subrange)
+-	s_arm_unwind_save_core (subrange);
+-
+-      s_arm_unwind_save_pseudo (mask_bit);
+-      range &= ~subrange;
+-      mask_range &= ~mask_bit;
+-    }
+-
+-  if (range)
+-    s_arm_unwind_save_core (range);
+-}
+-
+ /* Parse an unwind_save directive.
+    If the argument is non-zero, this is a .vsave directive.  */
+ 
+ static void
+ s_arm_unwind_save (int arch_v6)
+ {
+-  char *peek, *mask_peek;
+-  long range, mask_range;
++  char *peek;
+   struct reg_entry *reg;
+   bool had_brace = false;
+ 
+@@ -4756,7 +4793,7 @@ s_arm_unwind_save (int arch_v6)
+     as_bad (MISSING_FNSTART);
+ 
+   /* Figure out what sort of save we have.  */
+-  peek = mask_peek = input_line_pointer;
++  peek = input_line_pointer;
+ 
+   if (*peek == '{')
+     {
+@@ -4788,20 +4825,13 @@ s_arm_unwind_save (int arch_v6)
+ 
+     case REG_TYPE_PSEUDO:
+     case REG_TYPE_RN:
+-      mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
+-      range = parse_reg_list (&input_line_pointer, REGLIST_RN);
+-
+-      if (range == FAIL || mask_range == FAIL)
+-	{
+-	  as_bad (_("expected register list"));
+-	  ignore_rest_of_line ();
+-	  return;
+-	}
+-
+-      demand_empty_rest_of_line ();
+-
+-      s_arm_unwind_save_mixed (range, mask_range);
+-      return;
++      {
++	if (had_brace)
++	  input_line_pointer++;
++	parse_dot_save (&input_line_pointer, -1);
++	demand_empty_rest_of_line ();
++	return;
++      }
+ 
+     case REG_TYPE_VFD:
+       if (arch_v6)
+@@ -23993,12 +24023,8 @@ static const struct reg_entry reg_names[
+   /* XScale accumulator registers.  */
+   REGNUM(acc,0,XSCALE), REGNUM(ACC,0,XSCALE),
+ 
+-  /* DWARF ABI defines RA_AUTH_CODE to 143. It also reserves 134-142 for future
+-     expansion.  RA_AUTH_CODE here is given the value 143 % 134 to make it easy
+-     for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
+-     134 + reg_number should the range 134 to 142 be used for more pseudo regs
+-     in the future.  This also helps fit RA_AUTH_CODE into a bitmask.  */
+-  REGDEF(ra_auth_code,12,PSEUDO),
++  /* AADWARF32 defines RA_AUTH_CODE to 143.  */
++  REGDEF(ra_auth_code,143,PSEUDO),
+ };
+ #undef REGDEF
+ #undef REGNUM
+@@ -27905,7 +27931,6 @@ create_unwind_entry (int have_data)
+   return 0;
+ }
+ 
+-
+ /* Initialize the DWARF-2 unwind information for this procedure.  */
+ 
+ void
+--- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
++++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
+@@ -10,11 +10,11 @@ Unwind section '.ARM.exidx' at offset 0x
+ 
+ 0x0 <foo>: @0x0
+   Compact model index: 1
+-  0x84 0x00 pop {r14}
+   0xb4      pop {ra_auth_code}
+   0x84 0x00 pop {r14}
+-  0xb4      pop {ra_auth_code}
+   0xa3      pop {r4, r5, r6, r7}
+   0xb4      pop {ra_auth_code}
++  0x84 0x00 pop {r14}
++  0xb4      pop {ra_auth_code}
+   0xa8      pop {r4, r14}
+   0xb0      finish
+--- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
++++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
+@@ -8,4 +8,4 @@
+ .*:     file format.*
+ 
+ Contents of section .ARM.extab:
+- 0000 (00840281 b40084b4 b0a8b4a3|81028400 b48400b4 a3b4a8b0) 00000000  .*
++ 0000 (84b40281 84b4a300 b0a8b400|8102b484 00a3b484 00b4a8b0) 00000000  .*




More information about the lede-commits mailing list