diff --git a/SOURCES/binutils-plugin-as-needed-correct.patch b/SOURCES/binutils-plugin-as-needed-correct.patch
new file mode 100644
index 0000000..e88b431
--- /dev/null
+++ b/SOURCES/binutils-plugin-as-needed-correct.patch
@@ -0,0 +1,42 @@
+--- binutils.orig/bfd/elf-bfd.h	2021-09-20 16:06:58.320914954 +0100
++++ binutils-2.30/bfd/elf-bfd.h	2021-09-20 16:26:11.307770371 +0100
+@@ -180,6 +180,8 @@ struct elf_link_hash_entry
+   /* Symbol has a non-weak reference from a non-shared object (other than
+      the object in which it is defined).  */
+   unsigned int ref_regular_nonweak : 1;
++  /* Symbol has a non-weak reference from a LTO IR object file.  */
++  unsigned int ref_ir_nonweak : 1;
+   /* Dynamic symbol has been adjustd.  */
+   unsigned int dynamic_adjusted : 1;
+   /* Symbol needs a copy reloc.  */
+--- binutils.orig/bfd/elflink.c	2021-09-29 14:36:01.294185139 +0100
++++ binutils-2.30/bfd/elflink.c	2021-09-29 14:39:08.113874485 +0100
+@@ -4663,7 +4663,12 @@ error_free_dyn:
+ 
+ 	  /* Plugin symbols aren't normal.  Don't set def/ref flags.  */
+ 	  if ((abfd->flags & BFD_PLUGIN) != 0)
+-	    ;
++	    {
++	      /* Except for this flag to track nonweak references.  */
++	      if (!definition
++		  && bind != STB_WEAK)
++		h->ref_ir_nonweak = 1;
++	    }
+ 	  else if (!dynamic)
+ 	    {
+ 	      if (! definition)
+@@ -4906,11 +4911,13 @@ error_free_dyn:
+ 	  if (!add_needed
+ 	      && matched
+ 	      && definition
++	      && h->root.type != bfd_link_hash_indirect
+ 	      && ((dynsym
+ 		   && h->ref_regular_nonweak)
+ 		  || (old_bfd != NULL
+ 		      && (old_bfd->flags & BFD_PLUGIN) != 0
+-		      && bind != STB_WEAK)
++		      && h->ref_ir_nonweak
++		      && !info->lto_all_symbols_read)
+ 		  || (h->ref_dynamic_nonweak
+ 		      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
+ 		      && !on_needed_list (elf_dt_name (abfd),
diff --git a/SOURCES/binutils-plugin-error.patch b/SOURCES/binutils-plugin-error.patch
new file mode 100644
index 0000000..8d9b580
--- /dev/null
+++ b/SOURCES/binutils-plugin-error.patch
@@ -0,0 +1,42 @@
+--- binutils.orig/bfd/plugin.c	2022-01-19 16:17:33.290999966 +0000
++++ binutils-2.30/bfd/plugin.c	2022-01-19 16:23:33.704473426 +0000
+@@ -349,7 +349,7 @@ try_claim (bfd *abfd)
+ }
+ 
+ static int
+-try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
++try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p, bfd_boolean build_list_p)
+ {
+   void *plugin_handle;
+   struct ld_plugin_tv tv[4];
+@@ -362,7 +362,11 @@ try_load_plugin (const char *pname, bfd
+   plugin_handle = dlopen (pname, RTLD_NOW);
+   if (!plugin_handle)
+     {
+-      _bfd_error_handler ("%s\n", dlerror ());
++      /* If we are building a list of viable plugins, then
++	 we do not bother the user with the details of any
++	 plugins that cannot be loaded.  */
++      if (! build_list_p)
++	_bfd_error_handler ("%s\n", dlerror ());
+       return 0;
+     }
+ 
+@@ -477,7 +481,7 @@ load_plugin (bfd *abfd)
+     return found;
+ 
+   if (plugin_name)
+-    return try_load_plugin (plugin_name, abfd, &has_plugin);
++    return try_load_plugin (plugin_name, abfd, &has_plugin, FALSE);
+ 
+   if (plugin_program_name == NULL)
+     return found;
+@@ -501,7 +505,7 @@ load_plugin (bfd *abfd)
+ 
+       full_name = concat (p, "/", ent->d_name, NULL);
+       if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
+-	found = try_load_plugin (full_name, abfd, &valid_plugin);
++	found = try_load_plugin (full_name, abfd, &valid_plugin, TRUE);
+       if (has_plugin <= 0)
+ 	has_plugin = valid_plugin;
+       free (full_name);
diff --git a/SOURCES/binutils-s390x-arch14.patch b/SOURCES/binutils-s390x-arch14.patch
new file mode 100644
index 0000000..1986fc6
--- /dev/null
+++ b/SOURCES/binutils-s390x-arch14.patch
@@ -0,0 +1,880 @@
+diff -rup binutils.orig/gas/config/tc-s390.c binutils-2.30/gas/config/tc-s390.c
+--- binutils.orig/gas/config/tc-s390.c	2021-09-29 15:59:10.710209740 +0100
++++ binutils-2.30/gas/config/tc-s390.c	2021-09-29 16:03:03.951577660 +0100
+@@ -293,6 +293,8 @@ s390_parse_cpu (const char *         arg
+     { STRING_COMMA_LEN ("z14"), STRING_COMMA_LEN ("arch12"),
+       S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
+     { STRING_COMMA_LEN (""), STRING_COMMA_LEN ("arch13"),
++      S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
++    { STRING_COMMA_LEN (""), STRING_COMMA_LEN ("arch14"),
+       S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }
+   };
+   static struct
+diff -rup binutils.orig/gas/doc/c-s390.texi binutils-2.30/gas/doc/c-s390.texi
+--- binutils.orig/gas/doc/c-s390.texi	2021-09-29 15:59:10.710209740 +0100
++++ binutils-2.30/gas/doc/c-s390.texi	2021-09-29 16:04:39.597908390 +0100
+@@ -18,7 +18,7 @@ and eleven chip levels. The architecture
+ Architecture (ESA) and the newer z/Architecture mode. The chip levels
+ are g5 (or arch3), g6, z900 (or arch5), z990 (or arch6), z9-109, z9-ec
+ (or arch7), z10 (or arch8), z196 (or arch9), zEC12 (or arch10), z13
+-(or arch11), z14 (or arch12), and arch13.
++(or arch11), z14 (or arch12), z15 (or arch13), or arch14.
+ 
+ @menu
+ * s390 Options::                Command-line Options.
+@@ -70,8 +70,9 @@ are recognized:
+ @code{z196} (or @code{arch9}),
+ @code{zEC12} (or @code{arch10}),
+ @code{z13} (or @code{arch11}),
+-@code{z14} (or @code{arch12}), and
+-@code{arch13}).
++@code{z14} (or @code{arch12}),
++@code{z15} (or @code{arch13}), and
++@code{arch14}.
+ 
+ Assembling an instruction that is not supported on the target
+ processor results in an error message.
+@@ -312,7 +313,7 @@ field. The notation changes as follows:
+ @cindex instruction formats, s390
+ @cindex s390 instruction formats
+ 
+-The Principles of Operation manuals lists 26 instruction formats where
++The Principles of Operation manuals lists 35 instruction formats where
+ some of the formats have multiple variants. For the @samp{.insn}
+ pseudo directive the assembler recognizes some of the formats.
+ Typically, the most general variant of the instruction format is used
+@@ -544,6 +545,54 @@ with the @samp{.insn} pseudo directive:
+ 0        8    12   16   20            32   36           47
+ @end verbatim
+ 
++@item VRV format: <insn> V1,D2(V2,B2),M3
++@verbatim
+++--------+----+----+----+-------------+----+------------+
++| OpCode | V1 | V2 | B2 |     D2      | M3 |   Opcode   |
+++--------+----+----+----+-------------+----+------------+
++0        8    12   16   20            32   36           47
++@end verbatim
++
++@item VRI format: <insn> V1,V2,I3,M4,M5
++@verbatim
+++--------+----+----+-------------+----+----+------------+
++| OpCode | V1 | V2 |     I3      | M5 | M4 |   Opcode   |
+++--------+----+----+-------------+----+----+------------+
++0        8    12   16            28   32   36           47
++@end verbatim
++
++@item VRX format: <insn> V1,D2(R2,B2),M3
++@verbatim
+++--------+----+----+----+-------------+----+------------+
++| OpCode | V1 | R2 | B2 |     D2      | M3 |   Opcode   |
+++--------+----+----+----+-------------+----+------------+
++0        8    12   16   20            32   36           47
++@end verbatim
++
++@item VRS format: <insn> R1,V3,D2(B2),M4
++@verbatim
+++--------+----+----+----+-------------+----+------------+
++| OpCode | R1 | V3 | B2 |     D2      | M4 |   Opcode   |
+++--------+----+----+----+-------------+----+------------+
++0        8    12   16   20            32   36           47
++@end verbatim
++
++@item VRR format: <insn> V1,V2,V3,M4,M5,M6
++@verbatim
+++--------+----+----+----+---+----+----+----+------------+
++| OpCode | V1 | V2 | V3 |///| M6 | M5 | M4 |   Opcode   |
+++--------+----+----+----+---+----+----+----+------------+
++0        8    12   16       24   28   32   36           47
++@end verbatim
++
++@item VSI format: <insn> V1,D2(B2),I3
++@verbatim
+++--------+---------+----+-------------+----+------------+
++| OpCode |   I3    | B2 |     D2      | V1 |   Opcode   |
+++--------+---------+----+-------------+----+------------+
++0        8         16   20            32   36           47
++@end verbatim
++
+ @end table
+ 
+ For the complete list of all instruction format variants see the
+diff -rup binutils.orig/gas/testsuite/gas/s390/esa-g5.d binutils-2.30/gas/testsuite/gas/s390/esa-g5.d
+--- binutils.orig/gas/testsuite/gas/s390/esa-g5.d	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/esa-g5.d	2021-09-29 16:00:26.051682531 +0100
+@@ -78,10 +78,14 @@ Disassembly of section .text:
+ .*:	07 29 [	 ]*bhr	%r9
+ .*:	07 f9 [	 ]*br	%r9
+ .*:	a7 95 00 00 [	 ]*bras	%r9,e2 <foo\+0xe2>
+-.*:	a7 64 00 00 [	 ]*jlh	e6 <foo\+0xe6>
+-.*:	a7 66 00 00 [	 ]*brct	%r6,ea <foo\+0xea>
+-.*:	84 69 00 00 [	 ]*brxh	%r6,%r9,ee <foo\+0xee>
+-.*:	85 69 00 00 [	 ]*brxle	%r6,%r9,f2 <foo\+0xf2>
++.*:	a7 65 00 00 [	 ]*bras	%r6,e6 <foo\+0xe6>
++.*:	a7 64 00 00 [	 ]*jlh	ea <foo\+0xea>
++.*:	a7 66 00 00 [	 ]*brct	%r6,ee <foo\+0xee>
++.*:	a7 66 00 00 [	 ]*brct	%r6,f2 <foo\+0xf2>
++.*:	84 69 00 00 [	 ]*brxh	%r6,%r9,f6 <foo\+0xf6>
++.*:	84 69 00 00 [	 ]*brxh	%r6,%r9,fa <foo\+0xfa>
++.*:	85 69 00 00 [	 ]*brxle	%r6,%r9,fe <foo\+0xfe>
++.*:	85 69 00 00 [	 ]*brxle	%r6,%r9,102 <foo\+0x102>
+ .*:	b2 5a 00 69 [	 ]*bsa	%r6,%r9
+ .*:	b2 58 00 69 [	 ]*bsg	%r6,%r9
+ .*:	0b 69 [	 ]*bsm	%r6,%r9
+@@ -180,27 +184,49 @@ Disassembly of section .text:
+ .*:	b2 21 00 69 [	 ]*ipte	%r6,%r9
+ .*:	b2 29 00 69 [	 ]*iske	%r6,%r9
+ .*:	b2 23 00 69 [	 ]*ivsk	%r6,%r9
+-.*:	a7 f4 00 00 [	 ]*j	278 <foo\+0x278>
+-.*:	a7 84 00 00 [	 ]*je	27c <foo\+0x27c>
+-.*:	a7 24 00 00 [	 ]*jh	280 <foo\+0x280>
+-.*:	a7 a4 00 00 [	 ]*jhe	284 <foo\+0x284>
+-.*:	a7 44 00 00 [	 ]*jl	288 <foo\+0x288>
+-.*:	a7 c4 00 00 [	 ]*jle	28c <foo\+0x28c>
+-.*:	a7 64 00 00 [	 ]*jlh	290 <foo\+0x290>
+-.*:	a7 44 00 00 [	 ]*jl	294 <foo\+0x294>
+-.*:	a7 74 00 00 [	 ]*jne	298 <foo\+0x298>
+-.*:	a7 d4 00 00 [	 ]*jnh	29c <foo\+0x29c>
+-.*:	a7 54 00 00 [	 ]*jnhe	2a0 <foo\+0x2a0>
+-.*:	a7 b4 00 00 [	 ]*jnl	2a4 <foo\+0x2a4>
+-.*:	a7 34 00 00 [	 ]*jnle	2a8 <foo\+0x2a8>
+-.*:	a7 94 00 00 [	 ]*jnlh	2ac <foo\+0x2ac>
+-.*:	a7 b4 00 00 [	 ]*jnl	2b0 <foo\+0x2b0>
+-.*:	a7 e4 00 00 [	 ]*jno	2b4 <foo\+0x2b4>
+-.*:	a7 d4 00 00 [	 ]*jnh	2b8 <foo\+0x2b8>
+-.*:	a7 74 00 00 [	 ]*jne	2bc <foo\+0x2bc>
+-.*:	a7 14 00 00 [	 ]*jo	2c0 <foo\+0x2c0>
+-.*:	a7 24 00 00 [	 ]*jh	2c4 <foo\+0x2c4>
+-.*:	a7 84 00 00 [	 ]*je	2c8 <foo\+0x2c8>
++.*:	a7 f4 00 00 [	 ]*j	288 <foo\+0x288>
++.*:	a7 84 00 00 [	 ]*je	28c <foo\+0x28c>
++.*:	a7 24 00 00 [	 ]*jh	290 <foo\+0x290>
++.*:	a7 a4 00 00 [	 ]*jhe	294 <foo\+0x294>
++.*:	a7 44 00 00 [	 ]*jl	298 <foo\+0x298>
++.*:	a7 c4 00 00 [	 ]*jle	29c <foo\+0x29c>
++.*:	a7 64 00 00 [	 ]*jlh	2a0 <foo\+0x2a0>
++.*:	a7 44 00 00 [	 ]*jl	2a4 <foo\+0x2a4>
++.*:	a7 74 00 00 [	 ]*jne	2a8 <foo\+0x2a8>
++.*:	a7 d4 00 00 [	 ]*jnh	2ac <foo\+0x2ac>
++.*:	a7 54 00 00 [	 ]*jnhe	2b0 <foo\+0x2b0>
++.*:	a7 b4 00 00 [	 ]*jnl	2b4 <foo\+0x2b4>
++.*:	a7 34 00 00 [	 ]*jnle	2b8 <foo\+0x2b8>
++.*:	a7 94 00 00 [	 ]*jnlh	2bc <foo\+0x2bc>
++.*:	a7 b4 00 00 [	 ]*jnl	2c0 <foo\+0x2c0>
++.*:	a7 e4 00 00 [	 ]*jno	2c4 <foo\+0x2c4>
++.*:	a7 d4 00 00 [	 ]*jnh	2c8 <foo\+0x2c8>
++.*:	a7 74 00 00 [	 ]*jne	2cc <foo\+0x2cc>
++.*:	a7 14 00 00 [	 ]*jo	2d0 <foo\+0x2d0>
++.*:	a7 24 00 00 [	 ]*jh	2d4 <foo\+0x2d4>
++.*:	a7 84 00 00 [	 ]*je	2d8 <foo\+0x2d8>
++.*:	a7 04 00 00 [	 ]*jnop	2dc <foo\+0x2dc>
++.*:	a7 14 00 00 [	 ]*jo	2e0 <foo\+0x2e0>
++.*:	a7 24 00 00 [	 ]*jh	2e4 <foo\+0x2e4>
++.*:	a7 24 00 00 [	 ]*jh	2e8 <foo\+0x2e8>
++.*:	a7 34 00 00 [	 ]*jnle	2ec <foo\+0x2ec>
++.*:	a7 44 00 00 [	 ]*jl	2f0 <foo\+0x2f0>
++.*:	a7 44 00 00 [	 ]*jl	2f4 <foo\+0x2f4>
++.*:	a7 54 00 00 [	 ]*jnhe	2f8 <foo\+0x2f8>
++.*:	a7 64 00 00 [	 ]*jlh	2fc <foo\+0x2fc>
++.*:	a7 74 00 00 [	 ]*jne	300 <foo\+0x300>
++.*:	a7 74 00 00 [	 ]*jne	304 <foo\+0x304>
++.*:	a7 84 00 00 [	 ]*je	308 <foo\+0x308>
++.*:	a7 84 00 00 [	 ]*je	30c <foo\+0x30c>
++.*:	a7 94 00 00 [	 ]*jnlh	310 <foo\+0x310>
++.*:	a7 a4 00 00 [	 ]*jhe	314 <foo\+0x314>
++.*:	a7 b4 00 00 [	 ]*jnl	318 <foo\+0x318>
++.*:	a7 b4 00 00 [	 ]*jnl	31c <foo\+0x31c>
++.*:	a7 c4 00 00 [	 ]*jle	320 <foo\+0x320>
++.*:	a7 d4 00 00 [	 ]*jnh	324 <foo\+0x324>
++.*:	a7 d4 00 00 [	 ]*jnh	328 <foo\+0x328>
++.*:	a7 e4 00 00 [	 ]*jno	32c <foo\+0x32c>
++.*:	a7 f4 00 00 [	 ]*j	330 <foo\+0x330>
+ .*:	ed 65 af ff 00 18 [	 ]*kdb	%f6,4095\(%r5,%r10\)
+ .*:	b3 18 00 69 [	 ]*kdbr	%f6,%f9
+ .*:	ed 65 af ff 00 08 [	 ]*keb	%f6,4095\(%r5,%r10\)
+@@ -483,4 +509,4 @@ Disassembly of section .text:
+ .*:	f8 58 5f ff af ff [	 ]*zap	4095\(6,%r5\),4095\(9,%r10\)
+ .*:	b2 21 b0 69 [	 ]*ipte	%r6,%r9,%r11
+ .*:	b2 21 bd 69 [	 ]*ipte	%r6,%r9,%r11,13
+-.*:	07 07 [ 	]*nopr	%r7
++.*:	07 07 [	 ]*nopr	%r7
+diff -rup binutils.orig/gas/testsuite/gas/s390/esa-g5.s binutils-2.30/gas/testsuite/gas/s390/esa-g5.s
+--- binutils.orig/gas/testsuite/gas/s390/esa-g5.s	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/esa-g5.s	2021-09-29 16:00:26.052682524 +0100
+@@ -72,10 +72,14 @@ foo:
+ 	bpr	%r9
+ 	br	%r9
+ 	bras	%r9,.
++	jas	%r6,.
+ 	brc	6,.
+ 	brct	6,.
++	jct	%r6,.
+ 	brxh	%r6,%r9,.
++	jxh	%r6,%r9,.
+ 	brxle	%r6,%r9,.
++	jxle	%r6,%r9,.
+ 	bsa	%r6,%r9
+ 	bsg	%r6,%r9
+ 	bsm	%r6,%r9
+@@ -195,6 +199,28 @@ foo:
+ 	jo	.
+ 	jp	.
+ 	jz	.
++	jnop	.
++	bro	.
++	brh	.
++	brp	.
++	brnle	.
++	brl	.
++	brm	.
++	brnhe	.
++	brlh	.
++	brne	.
++	brnz	.
++	bre	.
++	brz	.
++	brnlh	.
++	brhe	.
++	brnl	.
++	brnm	.
++	brle	.
++	brnh	.
++	brnp	.
++	brno	.
++	bru	.
+ 	kdb	%f6,4095(%r5,%r10)
+ 	kdbr	%f6,%f9
+ 	keb	%f6,4095(%r5,%r10)
+diff -rup binutils.orig/gas/testsuite/gas/s390/esa-z900.d binutils-2.30/gas/testsuite/gas/s390/esa-z900.d
+--- binutils.orig/gas/testsuite/gas/s390/esa-z900.d	2021-09-29 15:59:10.717209691 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/esa-z900.d	2021-09-29 16:00:26.052682524 +0100
+@@ -6,29 +6,52 @@
+ Disassembly of section .text:
+ 
+ .* <foo>:
+-.*:	c0 f4 00 00 00 00 [	 ]*jg	0 \<foo\>
+-.*:	c0 14 00 00 00 00 [	 ]*jgo	6 \<foo\+0x6>
+-.*:	c0 24 00 00 00 00 [	 ]*jgh	c \<foo\+0xc>
+-.*:	c0 24 00 00 00 00 [	 ]*jgh	12 \<foo\+0x12>
+-.*:	c0 34 00 00 00 00 [	 ]*jgnle	18 \<foo\+0x18>
+-.*:	c0 44 00 00 00 00 [	 ]*jgl	1e \<foo\+0x1e>
+-.*:	c0 44 00 00 00 00 [	 ]*jgl	24 \<foo\+0x24>
+-.*:	c0 54 00 00 00 00 [	 ]*jgnhe	2a \<foo\+0x2a>
+-.*:	c0 64 00 00 00 00 [	 ]*jglh	30 \<foo\+0x30>
+-.*:	c0 74 00 00 00 00 [	 ]*jgne	36 \<foo\+0x36>
+-.*:	c0 74 00 00 00 00 [	 ]*jgne	3c \<foo\+0x3c>
+-.*:	c0 84 00 00 00 00 [	 ]*jge	42 \<foo\+0x42>
+-.*:	c0 84 00 00 00 00 [	 ]*jge	48 \<foo\+0x48>
+-.*:	c0 94 00 00 00 00 [	 ]*jgnlh	4e \<foo\+0x4e>
+-.*:	c0 a4 00 00 00 00 [	 ]*jghe	54 \<foo\+0x54>
+-.*:	c0 b4 00 00 00 00 [	 ]*jgnl	5a \<foo\+0x5a>
+-.*:	c0 b4 00 00 00 00 [	 ]*jgnl	60 \<foo\+0x60>
+-.*:	c0 c4 00 00 00 00 [	 ]*jgle	66 \<foo\+0x66>
+-.*:	c0 d4 00 00 00 00 [	 ]*jgnh	6c \<foo\+0x6c>
+-.*:	c0 d4 00 00 00 00 [	 ]*jgnh	72 \<foo\+0x72>
+-.*:	c0 e4 00 00 00 00 [	 ]*jgno	78 \<foo\+0x78>
+-.*:	c0 f4 00 00 00 00 [	 ]*jg	7e \<foo\+0x7e>
+-.*:	c0 65 00 00 00 00 [	 ]*brasl	%r6,84 \<foo\+0x84>
++.*:	c0 f4 00 00 00 00 [	 ]*jg	0 <foo>
++.*:	c0 04 00 00 00 00 [	 ]*jgnop	6 <foo\+0x6>
++.*:	c0 14 00 00 00 00 [	 ]*jgo	c <foo\+0xc>
++.*:	c0 24 00 00 00 00 [	 ]*jgh	12 <foo\+0x12>
++.*:	c0 24 00 00 00 00 [	 ]*jgh	18 <foo\+0x18>
++.*:	c0 34 00 00 00 00 [	 ]*jgnle	1e <foo\+0x1e>
++.*:	c0 44 00 00 00 00 [	 ]*jgl	24 <foo\+0x24>
++.*:	c0 44 00 00 00 00 [	 ]*jgl	2a <foo\+0x2a>
++.*:	c0 54 00 00 00 00 [	 ]*jgnhe	30 <foo\+0x30>
++.*:	c0 64 00 00 00 00 [	 ]*jglh	36 <foo\+0x36>
++.*:	c0 74 00 00 00 00 [	 ]*jgne	3c <foo\+0x3c>
++.*:	c0 74 00 00 00 00 [	 ]*jgne	42 <foo\+0x42>
++.*:	c0 84 00 00 00 00 [	 ]*jge	48 <foo\+0x48>
++.*:	c0 84 00 00 00 00 [	 ]*jge	4e <foo\+0x4e>
++.*:	c0 94 00 00 00 00 [	 ]*jgnlh	54 <foo\+0x54>
++.*:	c0 a4 00 00 00 00 [	 ]*jghe	5a <foo\+0x5a>
++.*:	c0 b4 00 00 00 00 [	 ]*jgnl	60 <foo\+0x60>
++.*:	c0 b4 00 00 00 00 [	 ]*jgnl	66 <foo\+0x66>
++.*:	c0 c4 00 00 00 00 [	 ]*jgle	6c <foo\+0x6c>
++.*:	c0 d4 00 00 00 00 [	 ]*jgnh	72 <foo\+0x72>
++.*:	c0 d4 00 00 00 00 [	 ]*jgnh	78 <foo\+0x78>
++.*:	c0 e4 00 00 00 00 [	 ]*jgno	7e <foo\+0x7e>
++.*:	c0 f4 00 00 00 00 [	 ]*jg	84 <foo\+0x84>
++.*:	c0 14 00 00 00 00 [	 ]*jgo	8a <foo\+0x8a>
++.*:	c0 24 00 00 00 00 [	 ]*jgh	90 <foo\+0x90>
++.*:	c0 24 00 00 00 00 [	 ]*jgh	96 <foo\+0x96>
++.*:	c0 34 00 00 00 00 [	 ]*jgnle	9c <foo\+0x9c>
++.*:	c0 44 00 00 00 00 [	 ]*jgl	a2 <foo\+0xa2>
++.*:	c0 44 00 00 00 00 [	 ]*jgl	a8 <foo\+0xa8>
++.*:	c0 54 00 00 00 00 [	 ]*jgnhe	ae <foo\+0xae>
++.*:	c0 64 00 00 00 00 [	 ]*jglh	b4 <foo\+0xb4>
++.*:	c0 74 00 00 00 00 [	 ]*jgne	ba <foo\+0xba>
++.*:	c0 74 00 00 00 00 [	 ]*jgne	c0 <foo\+0xc0>
++.*:	c0 84 00 00 00 00 [	 ]*jge	c6 <foo\+0xc6>
++.*:	c0 84 00 00 00 00 [	 ]*jge	cc <foo\+0xcc>
++.*:	c0 94 00 00 00 00 [	 ]*jgnlh	d2 <foo\+0xd2>
++.*:	c0 a4 00 00 00 00 [	 ]*jghe	d8 <foo\+0xd8>
++.*:	c0 b4 00 00 00 00 [	 ]*jgnl	de <foo\+0xde>
++.*:	c0 b4 00 00 00 00 [	 ]*jgnl	e4 <foo\+0xe4>
++.*:	c0 c4 00 00 00 00 [	 ]*jgle	ea <foo\+0xea>
++.*:	c0 d4 00 00 00 00 [	 ]*jgnh	f0 <foo\+0xf0>
++.*:	c0 d4 00 00 00 00 [	 ]*jgnh	f6 <foo\+0xf6>
++.*:	c0 e4 00 00 00 00 [	 ]*jgno	fc <foo\+0xfc>
++.*:	c0 f4 00 00 00 00 [	 ]*jg	102 <foo\+0x102>
++.*:	c0 65 00 00 00 00 [	 ]*brasl	%r6,108 <foo\+0x108>
++.*:	c0 65 00 00 00 00 [	 ]*brasl	%r6,10e <foo\+0x10e>
+ .*:	01 0b [	 ]*tam
+ .*:	01 0c [	 ]*sam24
+ .*:	01 0d [	 ]*sam31
+@@ -39,7 +62,7 @@ Disassembly of section .text:
+ .*:	b9 97 00 69 [	 ]*dlr	%r6,%r9
+ .*:	b9 98 00 69 [	 ]*alcr	%r6,%r9
+ .*:	b9 99 00 69 [	 ]*slbr	%r6,%r9
+-.*:	c0 60 00 00 00 00 [	 ]*larl	%r6,ac \<foo\+0xac\>
++.*:	c0 60 00 00 00 00 [	 ]*larl	%r6,136 <foo\+0x136>
+ .*:	e3 65 af ff 00 1e [	 ]*lrv	%r6,4095\(%r5,%r10\)
+ .*:	e3 65 af ff 00 1f [	 ]*lrvh	%r6,4095\(%r5,%r10\)
+ .*:	e3 65 af ff 00 3e [	 ]*strv	%r6,4095\(%r5,%r10\)
+@@ -49,3 +72,4 @@ Disassembly of section .text:
+ .*:	e3 65 af ff 00 98 [	 ]*alc	%r6,4095\(%r5,%r10\)
+ .*:	e3 65 af ff 00 99 [	 ]*slb	%r6,4095\(%r5,%r10\)
+ .*:	eb 69 5f ff 00 1d [	 ]*rll	%r6,%r9,4095\(%r5\)
++.*:	07 07 [	 ]*nopr	%r7
+diff -rup binutils.orig/gas/testsuite/gas/s390/esa-z900.s binutils-2.30/gas/testsuite/gas/s390/esa-z900.s
+--- binutils.orig/gas/testsuite/gas/s390/esa-z900.s	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/esa-z900.s	2021-09-29 16:00:26.053682517 +0100
+@@ -1,6 +1,7 @@
+ .text
+ foo:
+ 	brcl	15,.
++	jgnop	.
+ 	jgo	.
+ 	jgh	.
+ 	jgp	.
+@@ -22,7 +23,29 @@ foo:
+ 	jgnp	.
+ 	jgno	.
+ 	jg	.
++	brol	.
++	brhl	.
++	brpl	.
++	brnlel	.
++	brll	.
++	brml	.
++	brnhel	.
++	brlhl	.
++	brnel	.
++	brnzl	.
++	brel	.
++	brzl	.
++	brnlhl	.
++	brhel	.
++	brnll	.
++	brnml	.
++	brlel	.
++	brnhl	.
++	brnpl	.
++	brnol	.
++	brul	.
+ 	brasl	%r6,.
++	jasl	%r6,.
+ 	tam
+ 	sam24
+ 	sam31
+diff -rup binutils.orig/gas/testsuite/gas/s390/s390.exp binutils-2.30/gas/testsuite/gas/s390/s390.exp
+--- binutils.orig/gas/testsuite/gas/s390/s390.exp	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/s390.exp	2021-09-29 16:01:42.244149395 +0100
+@@ -30,6 +30,7 @@ if [expr [istarget "s390-*-*"] ||  [ista
+     run_dump_test "zarch-z13" "{as -m64} {as -march=z13}"
+     run_dump_test "zarch-arch12" "{as -m64} {as -march=arch12}"
+     run_dump_test "zarch-arch13" "{as -m64} {as -march=arch13}"
++    run_dump_test "zarch-arch14" "{as -m64} {as -march=arch14}"
+     run_dump_test "zarch-reloc" "{as -m64}"
+     run_dump_test "zarch-operands" "{as -m64} {as -march=z9-109}"
+     run_dump_test "zarch-machine" "{as -m64} {as -march=z900}"
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-z10.d binutils-2.30/gas/testsuite/gas/s390/zarch-z10.d
+--- binutils.orig/gas/testsuite/gas/s390/zarch-z10.d	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-z10.d	2021-09-29 16:01:16.115332226 +0100
+@@ -362,11 +362,13 @@ Disassembly of section .text:
+ .*:	ec 67 d2 dc e6 54 [	 ]*rnsbg	%r6,%r7,210,220,230
+ .*:	ec 67 d2 dc e6 57 [	 ]*rxsbg	%r6,%r7,210,220,230
+ .*:	ec 67 d2 dc e6 56 [	 ]*rosbg	%r6,%r7,210,220,230
+-.*:	ec 67 d2 dc e6 55 [	 ]*risbg	%r6,%r7,210,220,230
+-.*:	c4 6f 00 00 00 00 [	 ]*strl	%r6,7f6 <foo\+0x7f6>
+-.*:	c4 6b 00 00 00 00 [	 ]*stgrl	%r6,7fc <foo\+0x7fc>
+-.*:	c4 67 00 00 00 00 [	 ]*sthrl	%r6,802 <foo\+0x802>
+-.*:	c6 60 00 00 00 00 [	 ]*exrl	%r6,808 <foo\+0x808>
++.*:	ec 67 d2 14 e6 55 [	 ]*risbg	%r6,%r7,210,20,230
++.*:	ec 67 d2 bc e6 55 [	 ]*risbgz	%r6,%r7,210,60,230
++.*:	ec 67 d2 94 e6 55 [	 ]*risbgz	%r6,%r7,210,20,230
++.*:	c4 6f 00 00 00 00 [	 ]*strl	%r6,802 <foo\+0x802>
++.*:	c4 6b 00 00 00 00 [	 ]*stgrl	%r6,808 <foo\+0x808>
++.*:	c4 67 00 00 00 00 [	 ]*sthrl	%r6,80e <foo\+0x80e>
++.*:	c6 60 00 00 00 00 [	 ]*exrl	%r6,814 <foo\+0x814>
+ .*:	af ee 6d 05 [	 ]*mc	3333\(%r6\),238
+ .*:	b9 a2 00 60 [	 ]*ptf	%r6
+ .*:	b9 af 00 67 [	 ]*pfmf	%r6,%r7
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-z10.s binutils-2.30/gas/testsuite/gas/s390/zarch-z10.s
+--- binutils.orig/gas/testsuite/gas/s390/zarch-z10.s	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-z10.s	2021-09-29 16:01:16.116332219 +0100
+@@ -356,7 +356,9 @@ foo:
+ 	rnsbg	%r6,%r7,210,220,230
+ 	rxsbg	%r6,%r7,210,220,230
+ 	rosbg	%r6,%r7,210,220,230
+-	risbg	%r6,%r7,210,220,230
++	risbg	%r6,%r7,210,20,230
++	risbg	%r6,%r7,210,188,230
++	risbgz	%r6,%r7,210,20,230
+ 	strl	%r6,.
+ 	stgrl	%r6,.
+ 	sthrl	%r6,.
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-z900.d binutils-2.30/gas/testsuite/gas/s390/zarch-z900.d
+--- binutils.orig/gas/testsuite/gas/s390/zarch-z900.d	2021-09-29 15:59:10.717209691 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-z900.d	2021-09-29 16:00:26.053682517 +0100
+@@ -20,8 +20,11 @@ Disassembly of section .text:
+ .*:	e3 95 af ff 00 46 [ 	]*bctg	%r9,4095\(%r5,%r10\)
+ .*:	b9 46 00 96 [ 	]*bctgr	%r9,%r6
+ .*:	a7 97 00 00 [	 ]*brctg	%r9,40 \<foo\+0x40\>
+-.*:	ec 96 00 00 00 44 [ 	]*brxhg	%r9,%r6,44 <foo\+0x44>
+-.*:	ec 96 00 00 00 45 [ 	]*brxlg	%r9,%r6,4a <foo\+0x4a>
++.*:	a7 67 00 00 [	 ]*brctg	%r6,44 <foo\+0x44>
++.*:	ec 96 00 00 00 44 [ 	]*brxhg	%r9,%r6,48 <foo\+0x48>
++.*:	ec 69 00 00 00 44 [	 ]*brxhg	%r6,%r9,4e <foo\+0x4e>
++.*:	ec 96 00 00 00 45 [ 	]*brxlg	%r9,%r6,54 <foo\+0x54>
++.*:	ec 69 00 00 00 45 [	 ]*brxlg	%r6,%r9,5a <foo\+0x5a>
+ .*:	eb 96 5f ff 00 44 [ 	]*bxhg	%r9,%r6,4095\(%r5\)
+ .*:	eb 96 5f ff 00 45 [ 	]*bxleg	%r9,%r6,4095\(%r5\)
+ .*:	b3 a5 00 96 [ 	]*cdgbr	%f9,%r6
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-z900.s binutils-2.30/gas/testsuite/gas/s390/zarch-z900.s
+--- binutils.orig/gas/testsuite/gas/s390/zarch-z900.s	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-z900.s	2021-09-29 16:00:26.053682517 +0100
+@@ -14,8 +14,11 @@ foo:
+ 	bctg	%r9,4095(%r5,%r10)
+ 	bctgr	%r9,%r6
+ 	brctg	%r9,.
++	jctg	%r6,.
+ 	brxhg	%r9,%r6,.
++	jxhg	%r6,%r9,.
+ 	brxlg	%r9,%r6,.
++	jxleg	%r6,%r9,.
+ 	bxhg	%r9,%r6,4095(%r5)
+ 	bxleg	%r9,%r6,4095(%r5)
+ 	cdgbr	%f9,%r6
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-zEC12.d binutils-2.30/gas/testsuite/gas/s390/zarch-zEC12.d
+--- binutils.orig/gas/testsuite/gas/s390/zarch-zEC12.d	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-zEC12.d	2021-09-29 16:01:16.116332219 +0100
+@@ -47,6 +47,8 @@ Disassembly of section .text:
+ .*:	eb 6c 7a 4d fe 2b [	 ]*clgtnh	%r6,-5555\(%r7\)
+ .*:	eb 6c 7a 4d fe 2b [	 ]*clgtnh	%r6,-5555\(%r7\)
+ .*:	ec 67 0c 0d 0e 59 [	 ]*risbgn	%r6,%r7,12,13,14
++.*:	ec 67 0c bc 0e 59 [	 ]*risbgnz	%r6,%r7,12,60,14
++.*:	ec 67 0c 94 0e 59 [	 ]*risbgnz	%r6,%r7,12,20,14
+ .*:	ed 0f 8f a0 6d aa [	 ]*cdzt	%f6,4000\(16,%r8\),13
+ .*:	ed 21 8f a0 4d ab [	 ]*cxzt	%f4,4000\(34,%r8\),13
+ .*:	ed 0f 8f a0 6d a8 [	 ]*czdt	%f6,4000\(16,%r8\),13
+@@ -54,16 +56,16 @@ Disassembly of section .text:
+ .*:	b2 e8 c0 56 [	 ]*ppa	%r5,%r6,12
+ .*:	b9 8f 60 59 [	 ]*crdte	%r5,%r6,%r9
+ .*:	b9 8f 61 59 [	 ]*crdte	%r5,%r6,%r9,1
+-.*:	c5 a0 0c 00 00 0c [	 ]*bprp	10,12a <bar>,12a <bar>
+-.*:	c5 a0 00 00 00 00 [	 ]*bprp	10,118 <foo\+0x118>,118 <foo\+0x118>
+-[	 ]*119: R_390_PLT12DBL	bar\+0x1
+-[	 ]*11b: R_390_PLT24DBL	bar\+0x3
+-.*:	c7 a0 00 00 00 00 [	 ]*bpp	10,11e <foo\+0x11e>,0
+-[	 ]*122: R_390_PLT16DBL	bar\+0x4
+-.*:	c7 a0 00 00 00 00 [	 ]*bpp	10,124 <foo\+0x124>,0
+-[	 ]*128: R_390_PC16DBL	baz\+0x4
++.*:	c5 a0 0c 00 00 0c [	 ]*bprp	10,136 <bar>,136 <bar>
++.*:	c5 a0 00 00 00 00 [	 ]*bprp	10,124 <foo\+0x124>,124 <foo\+0x124>
++[	 ]*125: R_390_PLT12DBL	bar\+0x1
++[	 ]*127: R_390_PLT24DBL	bar\+0x3
++.*:	c7 a0 00 00 00 00 [	 ]*bpp	10,12a <foo\+0x12a>,0
++[	 ]*12e: R_390_PLT16DBL	bar\+0x4
++.*:	c7 a0 00 00 00 00 [	 ]*bpp	10,130 <foo\+0x130>,0
++[	 ]*134: R_390_PC16DBL	baz\+0x4
+ 
+ 
+-000000000000012a <bar>:
++0000000000000136 <bar>:
+ 
+ .*:	07 07 [	 ]*nopr	%r7
+diff -rup binutils.orig/gas/testsuite/gas/s390/zarch-zEC12.s binutils-2.30/gas/testsuite/gas/s390/zarch-zEC12.s
+--- binutils.orig/gas/testsuite/gas/s390/zarch-zEC12.s	2021-09-29 15:59:10.716209698 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-zEC12.s	2021-09-29 16:01:16.116332219 +0100
+@@ -44,6 +44,9 @@ foo:
+ 	clgtnh	%r6,-5555(%r7)
+ 
+ 	risbgn	%r6,%r7,12,13,14
++	risbgn	%r6,%r7,12,188,14
++	risbgnz	%r6,%r7,12,20,14
++
+ 	cdzt	%f6,4000(16,%r8),13
+ 	cxzt	%f4,4000(34,%r8),13
+ 	czdt	%f6,4000(16,%r8),13
+diff -rup binutils.orig/include/opcode/s390.h binutils-2.30/include/opcode/s390.h
+--- binutils.orig/include/opcode/s390.h	2021-09-29 15:59:10.908208355 +0100
++++ binutils-2.30/include/opcode/s390.h	2021-09-29 16:01:42.245149388 +0100
+@@ -44,6 +44,7 @@ enum s390_opcode_cpu_val
+     S390_OPCODE_Z13,
+     S390_OPCODE_ARCH12,
+     S390_OPCODE_ARCH13,
++    S390_OPCODE_ARCH14,
+     S390_OPCODE_MAXCPU
+   };
+ 
+diff -rup binutils.orig/ld/ChangeLog.orig binutils-2.30/ld/ChangeLog.orig
+--- binutils.orig/ld/ChangeLog.orig	2021-09-29 15:59:10.935208166 +0100
++++ binutils-2.30/ld/ChangeLog.orig	2021-09-29 16:00:26.053682517 +0100
+@@ -1,3 +1,27 @@
++2018-01-27  Nick Clifton  <nickc@redhat.com>
++
++	This is the 2.30 release:
++
++	* configure: Regenerate.
++	* po/ld.pot: Regenerate.
++
++2018-01-27  Nick Clifton  <nickc@redhat.com>
++
++	PR 22751
++	Revert this change as a temporary solution for this PR:
++
++	2017-09-02  Alan Modra  <amodra@gmail.com>
++
++	* ldlang.h (lang_input_statement_type): Expand comments.
++	(LANG_FOR_EACH_INPUT_STATEMENT): Rewrite without casts.
++	* ldlang.c (lang_for_each_input_file): Likewise.
++	(load_symbols): Set usrdata for archives.
++	(find_rescan_insertion): New function.
++	(lang_process): Trim off and reinsert entries added to file chain
++	when rescanning archives for LTO.
++	* ldmain.c (add_archive_element): Set my_archive input_statement
++	next pointer to last element added.
++
+ 2018-01-25  Eric Botcazou  <ebotcazou@adacore.com>
+ 
+ 	* testsuite/ld-sparc/sparc.exp (32-bit: Helper shared library):
+diff -rup binutils.orig/ld/ChangeLog.rej binutils-2.30/ld/ChangeLog.rej
+--- binutils.orig/ld/ChangeLog.rej	2021-09-29 15:59:10.935208166 +0100
++++ binutils-2.30/ld/ChangeLog.rej	2021-09-29 16:00:26.053682517 +0100
+@@ -1,18 +1,11 @@
+ --- ld/ChangeLog
+ +++ ld/ChangeLog
+-@@ -1,15 +1,3 @@
+--2017-09-02  Alan Modra  <amodra@gmail.com>
+--
+--	* ldlang.h (lang_input_statement_type): Expand comments.
+--	(LANG_FOR_EACH_INPUT_STATEMENT): Rewrite without casts.
+--	* ldlang.c (lang_for_each_input_file): Likewise.
+--	(load_symbols): Set usrdata for archives.
+--	(find_rescan_insertion): New function.
+--	(lang_process): Trim off and reinsert entries added to file chain
+--	when rescanning archives for LTO.
+--	* ldmain.c (add_archive_element): Set my_archive input_statement
+--	next pointer to last element added.
+--
+- 2017-09-01  H.J. Lu  <hongjiu.lu@intel.com>
++@@ -1,3 +1,8 @@
+++2020-12-03  Andreas Krebbel  <krebbel@linux.ibm.com>
+++
+++	* testsuite/ld-s390/tlsbin_64.dd: The newly added jgnop mnemonic
+++	replaces long relative branches with empty condition code masks.
+++
++ 2020-12-03  Maciej W. Rozycki  <macro@linux-mips.org>
+  
+- 	PR ld/22064
++ 	* testsuite/ld-vax-elf/vax-elf.exp: Wrap excessively long lines
+diff -rup binutils.orig/ld/testsuite/ld-s390/tlsbin_64.dd binutils-2.30/ld/testsuite/ld-s390/tlsbin_64.dd
+--- binutils.orig/ld/testsuite/ld-s390/tlsbin_64.dd	2021-09-29 15:59:10.988207795 +0100
++++ binutils-2.30/ld/testsuite/ld-s390/tlsbin_64.dd	2021-09-29 16:00:26.053682517 +0100
+@@ -87,26 +87,26 @@ Disassembly of section .text:
+  +[0-9a-f]+:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+ # GD -> LE with global variable defined in executable
+  +[0-9a-f]+:	e3 20 d0 10 00 04 	lg	%r2,16\(%r13\)
+- +[0-9a-f]+:	c0 04 00 00 00 00 	brcl	0,[0-9a-f]+ <fn2\+0xca>
++ +[0-9a-f]+:	c0 04 00 00 00 00 	jgnop	[0-9a-f]+ <fn2\+0xca>
+  +[0-9a-f]+:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+ # GD -> LE with local variable defined in executable
+  +[0-9a-f]+:	e3 20 d0 18 00 04 	lg	%r2,24\(%r13\)
+- +[0-9a-f]+:	c0 04 00 00 00 00 	brcl	0,[0-9a-f]+ <fn2\+0xda>
++ +[0-9a-f]+:	c0 04 00 00 00 00 	jgnop	[0-9a-f]+ <fn2\+0xda>
+  +[0-9a-f]+:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+ # GD -> LE with hidden variable defined in executable
+  +[0-9a-f]+:	e3 20 d0 20 00 04 	lg	%r2,32\(%r13\)
+- +[0-9a-f]+:	c0 04 00 00 00 00 	brcl	0,[0-9a-f]+ <fn2\+0xea>
++ +[0-9a-f]+:	c0 04 00 00 00 00 	jgnop	[0-9a-f]+ <fn2\+0xea>
+  +[0-9a-f]+:	41 22 90 00       	la	%r2,0\(%r2,%r9\)
+ # LD -> LE
+  +[0-9a-f]+:	e3 20 d0 28 00 04 	lg	%r2,40\(%r13\)
+- +[0-9a-f]+:	c0 04 00 00 00 00 	brcl	0,[0-9a-f]+ <fn2\+0xfa>
++ +[0-9a-f]+:	c0 04 00 00 00 00 	jgnop	[0-9a-f]+ <fn2\+0xfa>
+  +[0-9a-f]+:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+  +[0-9a-f]+:	e3 40 d0 30 00 04 	lg	%r4,48\(%r13\)
+  +[0-9a-f]+:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+  +[0-9a-f]+:	e3 40 d0 38 00 04 	lg	%r4,56\(%r13\)
+  +[0-9a-f]+:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+  +[0-9a-f]+:	e3 20 d0 40 00 04 	lg	%r2,64\(%r13\)
+- +[0-9a-f]+:	c0 04 00 00 00 00 	brcl	0,[0-9a-f]+ <fn2\+0x11e>
++ +[0-9a-f]+:	c0 04 00 00 00 00 	jgnop	[0-9a-f]+ <fn2\+0x11e>
+  +[0-9a-f]+:	41 32 90 00       	la	%r3,0\(%r2,%r9\)
+  +[0-9a-f]+:	e3 40 d0 48 00 04 	lg	%r4,72\(%r13\)
+  +[0-9a-f]+:	41 54 30 00       	la	%r5,0\(%r4,%r3\)
+diff -rup binutils.orig/opcodes/s390-mkopc.c binutils-2.30/opcodes/s390-mkopc.c
+--- binutils.orig/opcodes/s390-mkopc.c	2021-09-29 15:59:10.934208173 +0100
++++ binutils-2.30/opcodes/s390-mkopc.c	2021-09-29 16:01:42.245149388 +0100
+@@ -379,6 +379,8 @@ main (void)
+ 	min_cpu = S390_OPCODE_ARCH12;
+       else if (strcmp (cpu_string, "arch13") == 0)
+ 	min_cpu = S390_OPCODE_ARCH13;
++      else if (strcmp (cpu_string, "arch14") == 0)
++	min_cpu = S390_OPCODE_ARCH14;
+       else {
+ 	fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string);
+ 	exit (1);
+diff -rup binutils.orig/opcodes/s390-opc.c binutils-2.30/opcodes/s390-opc.c
+--- binutils.orig/opcodes/s390-opc.c	2021-09-29 15:59:10.928208215 +0100
++++ binutils-2.30/opcodes/s390-opc.c	2021-09-29 16:04:54.977800770 +0100
+@@ -218,32 +218,34 @@ const struct s390_operand s390_operands[
+   { 8, 8, 0 },
+ #define U8_16       68            /* 8 bit unsigned value starting at 16 */
+   { 8, 16, 0 },
+-#define U8_24       69            /* 8 bit unsigned value starting at 24 */
++#define U6_26       69            /* 6 bit unsigned value starting at 26 */
++  { 6, 26, 0 },
++#define U8_24       70            /* 8 bit unsigned value starting at 24 */
+   { 8, 24, 0 },
+-#define U8_28       70            /* 8 bit unsigned value starting at 28 */
++#define U8_28       71            /* 8 bit unsigned value starting at 28 */
+   { 8, 28, 0 },
+-#define U8_32       71            /* 8 bit unsigned value starting at 32 */
++#define U8_32       72            /* 8 bit unsigned value starting at 32 */
+   { 8, 32, 0 },
+-#define U12_16      72            /* 12 bit unsigned value starting at 16 */
++#define U12_16      73            /* 12 bit unsigned value starting at 16 */
+   { 12, 16, 0 },
+-#define U16_16      73            /* 16 bit unsigned value starting at 16 */
++#define U16_16      74            /* 16 bit unsigned value starting at 16 */
+   { 16, 16, 0 },
+-#define U16_32      74		  /* 16 bit unsigned value starting at 32 */
++#define U16_32      75		  /* 16 bit unsigned value starting at 32 */
+   { 16, 32, 0 },
+-#define U32_16      75		  /* 32 bit unsigned value starting at 16 */
++#define U32_16      76		  /* 32 bit unsigned value starting at 16 */
+   { 32, 16, 0 },
+ 
+ /* PC-relative address operands.  */
+ 
+-#define J12_12      76            /* 12 bit PC relative offset at 12 */
++#define J12_12      77            /* 12 bit PC relative offset at 12 */
+   { 12, 12, S390_OPERAND_PCREL },
+-#define J16_16      77            /* 16 bit PC relative offset at 16 */
++#define J16_16      78            /* 16 bit PC relative offset at 16 */
+   { 16, 16, S390_OPERAND_PCREL },
+-#define J16_32      78            /* 16 bit PC relative offset at 32 */
++#define J16_32      79            /* 16 bit PC relative offset at 32 */
+   { 16, 32, S390_OPERAND_PCREL },
+-#define J24_24      79            /* 24 bit PC relative offset at 24 */
++#define J24_24      80            /* 24 bit PC relative offset at 24 */
+   { 24, 24, S390_OPERAND_PCREL },
+-#define J32_16      80            /* 32 bit PC relative offset at 16 */
++#define J32_16      81            /* 32 bit PC relative offset at 16 */
+   { 32, 16, S390_OPERAND_PCREL },
+ 
+ };
+@@ -313,6 +315,7 @@ const struct s390_operand s390_operands[
+ #define INSTR_RIE_R0U0     6, { R_8,U16_16,0,0,0,0 }             /* e.g. clfitne */
+ #define INSTR_RIE_RUI0     6, { R_8,I16_16,U4_12,0,0,0 }         /* e.g. lochi */
+ #define INSTR_RIE_RRUUU    6, { R_8,R_12,U8_16,U8_24,U8_32,0 }   /* e.g. rnsbg */
++#define INSTR_RIE_RRUUU2   6, { R_8,R_12,U8_16,U6_26,U8_32,0 }   /* e.g. rnsbg */
+ #define INSTR_RIL_0P       6, { J32_16,0,0,0,0 }                 /* e.g. jg    */
+ #define INSTR_RIL_RP       6, { R_8,J32_16,0,0,0,0 }             /* e.g. brasl */
+ #define INSTR_RIL_UP       6, { U4_8,J32_16,0,0,0,0 }            /* e.g. brcl  */
+@@ -439,6 +442,7 @@ const struct s390_operand s390_operands[
+ #define INSTR_RX_URRD      4, { U4_8,D_20,X_12,B_16,0,0 }        /* e.g. bc    */
+ #define INSTR_SI_RD        4, { D_20,B_16,0,0,0,0 }              /* e.g. lpsw  */
+ #define INSTR_SI_URD       4, { D_20,B_16,U8_8,0,0,0 }           /* e.g. cli   */
++#define INSTR_SIY_RD       6, { D20_20,B_16,0,0,0,0 }            /* e.g. lpswey*/
+ #define INSTR_SIY_URD      6, { D20_20,B_16,U8_8,0,0,0 }         /* e.g. tmy   */
+ #define INSTR_SIY_IRD      6, { D20_20,B_16,I8_8,0,0,0 }         /* e.g. asi   */
+ #define INSTR_SIL_RDI      6, { D_20,B_16,I16_32,0,0,0 }         /* e.g. chhsi */
+@@ -534,6 +538,7 @@ const struct s390_operand s390_operands[
+ #define MASK_RIE_R0U0     { 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff }
+ #define MASK_RIE_RUI0     { 0xff, 0x00, 0x00, 0x00, 0xff, 0xff }
+ #define MASK_RIE_RRUUU    { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
++#define MASK_RIE_RRUUU2   { 0xff, 0x00, 0x00, 0xc0, 0x00, 0xff }
+ #define MASK_RIL_0P       { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+ #define MASK_RIL_RP       { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
+ #define MASK_RIL_UP       { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
+@@ -660,6 +665,7 @@ const struct s390_operand s390_operands[
+ #define MASK_RX_URRD      { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ #define MASK_SI_RD        { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ #define MASK_SI_URD       { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }
++#define MASK_SIY_RD       { 0xff, 0xff, 0x00, 0x00, 0x00, 0xff }
+ #define MASK_SIY_URD      { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+ #define MASK_SIY_IRD      { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+ #define MASK_SIL_RDI      { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
+diff -rup binutils.orig/opcodes/s390-opc.txt binutils-2.30/opcodes/s390-opc.txt
+--- binutils.orig/opcodes/s390-opc.txt	2021-09-29 15:59:10.933208180 +0100
++++ binutils-2.30/opcodes/s390-opc.txt	2021-09-29 16:05:08.818703921 +0100
+@@ -246,10 +246,14 @@ d7 xc SS_L0RDRD "exclusive OR" g5 esa,za
+ f8 zap SS_LLRDRD "zero and add" g5 esa,zarch
+ a70a ahi RI_RI "add halfword immediate" g5 esa,zarch
+ 84 brxh RSI_RRP "branch relative on index high" g5 esa,zarch
++84 jxh RSI_RRP "branch relative on index high" g5 esa,zarch
+ 85 brxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch
++85 jxle RSI_RRP "branch relative on index low or equal" g5 esa,zarch
+ a705 bras RI_RP "branch relative and save" g5 esa,zarch
++a705 jas RI_RP "branch relative and save" g5 esa,zarch
+ a704 brc RI_UP "branch relative on condition" g5 esa,zarch
+ a706 brct RI_RP "branch relative on count" g5 esa,zarch
++a706 jct RI_RP "branch relative on count" g5 esa,zarch
+ b241 cksm RRE_RR "checksum" g5 esa,zarch
+ a70e chi RI_RI "compare halfword immediate" g5 esa,zarch
+ a9 clcle RS_RRRD "compare logical long extended" g5 esa,zarch
+@@ -268,8 +272,11 @@ a701 tml RI_RU "test under mask low" g5
+ 4700 nop RX_0RRD "no operation" g5 esa,zarch optparm
+ 4700 b*8 RX_0RRD "conditional branch" g5 esa,zarch
+ 47f0 b RX_0RRD "unconditional branch" g5 esa,zarch
++a704 jnop RI_0P "nop jump" g5 esa,zarch
+ a704 j*8 RI_0P "conditional jump" g5 esa,zarch
++a704 br*8 RI_0P "conditional jump" g5 esa,zarch
+ a7f4 j RI_0P "unconditional jump" g5 esa,zarch
++a7f4 bru RI_0P "unconditional jump" g5 esa,zarch
+ b34a axbr RRE_FEFE "add extended bfp" g5 esa,zarch
+ b31a adbr RRE_FF "add long bfp" g5 esa,zarch
+ ed000000001a adb RXE_FRRD "add long bfp" g5 esa,zarch
+@@ -437,7 +444,9 @@ e3000000001b slgf RXE_RRRD "subtract log
+ e3000000000c msg RXE_RRRD "multiply single 64" z900 zarch
+ e3000000001c msgf RXE_RRRD "multiply single 64<32" z900 zarch
+ ec0000000044 brxhg RIE_RRP "branch relative on index high 64" z900 zarch
++ec0000000044 jxhg RIE_RRP "branch relative on index high 64" z900 zarch
+ ec0000000045 brxlg RIE_RRP "branch relative on index low or equal 64" z900 zarch
++ec0000000045 jxleg RIE_RRP "branch relative on index low or equal 64" z900 zarch
+ eb0000000044 bxhg RSE_RRRD "branch on index high 64" z900 zarch
+ eb0000000045 bxleg RSE_RRRD "branch on index low or equal 64" z900 zarch
+ eb000000000c srlg RSE_RRRD "shift right single logical 64" z900 zarch
+@@ -462,10 +471,15 @@ eb0000000080 icmh RSE_RURD "insert chara
+ a702 tmhh RI_RU "test under mask high high" z900 zarch
+ a703 tmhl RI_RU "test under mask high low" z900 zarch
+ c004 brcl RIL_UP "branch relative on condition long" z900 esa,zarch
++c004 jgnop RIL_0P "nop jump long" z900 esa,zarch
+ c004 jg*8 RIL_0P "conditional jump long" z900 esa,zarch
++c004 br*8l RIL_0P "conditional jump long" z900 esa,zarch
+ c0f4 jg RIL_0P "unconditional jump long" z900 esa,zarch
++c0f4 brul RIL_0P "unconditional jump long" z900 esa,zarch
+ c005 brasl RIL_RP "branch relative and save long" z900 esa,zarch
++c005 jasl RIL_RP "branch relative and save long" z900 esa,zarch
+ a707 brctg RI_RP "branch relative on count 64" z900 zarch
++a707 jctg RI_RP "branch relative on count 64" z900 zarch
+ a709 lghi RI_RI "load halfword immediate 64" z900 zarch
+ a70b aghi RI_RI "add halfword immediate 64" z900 zarch
+ a70d mghi RI_RI "multiply halfword immediate 64" z900 zarch
+@@ -956,6 +970,7 @@ ec0000000054 rnsbg RIE_RRUUU "rotate the
+ ec0000000057 rxsbg RIE_RRUUU "rotate then exclusive or selected bits" z10 zarch
+ ec0000000056 rosbg RIE_RRUUU "rotate then or selected bits" z10 zarch
+ ec0000000055 risbg RIE_RRUUU "rotate then insert selected bits" z10 zarch
++ec0000800055 risbgz RIE_RRUUU2 "rotate then insert selected bits and zero remaining bits" z10 zarch
+ c40f strl RIL_RP "store relative long (32)" z10 zarch
+ c40b stgrl RIL_RP "store relative long (64)" z10 zarch
+ c407 sthrl RIL_RP "store halfword relative long" z10 zarch
+@@ -1139,6 +1154,7 @@ eb0000000023 clt$12 RSY_R0RD "compare lo
+ eb000000002b clgt RSY_RURD "compare logical and trap 64 bit reg-mem" zEC12 zarch
+ eb000000002b clgt$12 RSY_R0RD "compare logical and trap 64 bit reg-mem" zEC12 zarch
+ ec0000000059 risbgn RIE_RRUUU "rotate then insert selected bits nocc" zEC12 zarch
++ec0000800059 risbgnz RIE_RRUUU2 "rotate then insert selected bits and zero remaining bits nocc" zEC12 zarch
+ ed00000000aa cdzt RSL_LRDFU "convert from zoned long" zEC12 zarch
+ ed00000000ab cxzt RSL_LRDFEU "convert from zoned extended" zEC12 zarch
+ ed00000000a8 czdt RSL_LRDFU "convert to zoned long" zEC12 zarch
+@@ -2001,3 +2017,33 @@ e60000000052 vcvbg VRR_RV0UU "vector con
+ # Message Security Assist Extension 9
+ 
+ b93a kdsa RRE_RR "compute digital signature authentication" arch13 zarch
++
++
++# arch14 instructions
++
++e60000000074 vschp VRR_VVV0U0U " " arch14 zarch
++e60000002074 vschsp VRR_VVV0U0 " " arch14 zarch
++e60000003074 vschdp VRR_VVV0U0 " " arch14 zarch
++e60000004074 vschxp VRR_VVV0U0 " " arch14 zarch
++e6000000007c vscshp VRR_VVV " " arch14 zarch
++e6000000007d vcsph VRR_VVV0U0 " " arch14 zarch
++e60000000051 vclzdp VRR_VV0U2 " " arch14 zarch
++e60000000070 vpkzr VRI_VVV0UU2 " " arch14 zarch
++e60000000072 vsrpr VRI_VVV0UU2 " " arch14 zarch
++e60000000054 vupkzh VRR_VV0U2 " " arch14 zarch
++e6000000005c vupkzl VRR_VV0U2 " " arch14 zarch
++
++b93b nnpa RRE_00 " " arch14 zarch
++e60000000056 vclfnh VRR_VV0UU2 " " arch14 zarch
++e6000000005e vclfnl VRR_VV0UU2 " " arch14 zarch
++e60000000075 vcrnf VRR_VVV0UU " " arch14 zarch
++e6000000005d vcfn VRR_VV0UU2 " " arch14 zarch
++e60000000055 vcnf VRR_VV0UU2 " " arch14 zarch
++
++b98B rdp RRF_RURR2 " " arch14 zarch optparm
++
++eb0000000071 lpswey SIY_RD " " arch14 zarch
++b200 lbear S_RD " " arch14 zarch
++b201 stbear S_RD " " arch14 zarch
++
++b28f qpaci S_RD " " arch14 zarch
+--- /dev/null	2021-09-29 08:55:29.386811947 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-arch14.s	2021-09-29 16:05:08.817703928 +0100
+@@ -0,0 +1,25 @@
++.text
++foo:
++	vschp	%v15,%v17,%v20,13,12
++	vschsp	%v15,%v17,%v20,13
++	vschdp	%v15,%v17,%v20,13
++	vschxp	%v15,%v17,%v20,13
++	vscshp	%v15,%v17,%v20
++	vcsph	%v15,%v17,%v20,13
++	vclzdp	%v15,%v17,13
++	vpkzr	%v15,%v17,%v20,253,12
++	vsrpr	%v15,%v17,%v20,253,12
++	vupkzh	%v15,%v17,13
++	vupkzl	%v15,%v17,13
++	nnpa
++	vclfnh	%v15,%v17,13,12
++	vclfnl	%v15,%v17,13,12
++	vcrnf	%v15,%v17,%v20,13,12
++	vcfn	%v15,%v17,13,12
++	vcnf	%v15,%v17,13,12
++	rdp	%r6,%r9,%r11
++	rdp	%r6,%r9,%r11,13
++	lpswey	-10000(%r6)
++	lbear	4000(%r6)
++	stbear	4000(%r6)
++	qpaci	4095(%r5)
+--- /dev/null	2021-09-29 08:55:29.386811947 +0100
++++ binutils-2.30/gas/testsuite/gas/s390/zarch-arch14.d	2021-09-29 16:05:08.817703928 +0100
+@@ -0,0 +1,32 @@
++#name: s390x opcode
++#objdump: -dr
++
++.*: +file format .*
++
++Disassembly of section .text:
++
++.* <foo>:
++.*:	e6 f1 40 c0 d6 74 [	 ]*vschp	%v15,%v17,%v20,13,12
++.*:	e6 f1 40 d0 26 74 [	 ]*vschsp	%v15,%v17,%v20,13
++.*:	e6 f1 40 d0 36 74 [	 ]*vschdp	%v15,%v17,%v20,13
++.*:	e6 f1 40 d0 46 74 [	 ]*vschxp	%v15,%v17,%v20,13
++.*:	e6 f1 40 00 06 7c [	 ]*vscshp	%v15,%v17,%v20
++.*:	e6 f1 40 d0 06 7d [	 ]*vcsph	%v15,%v17,%v20,13
++.*:	e6 f1 00 d0 04 51 [	 ]*vclzdp	%v15,%v17,13
++.*:	e6 f1 40 cf d6 70 [	 ]*vpkzr	%v15,%v17,%v20,253,12
++.*:	e6 f1 40 cf d6 72 [	 ]*vsrpr	%v15,%v17,%v20,253,12
++.*:	e6 f1 00 d0 04 54 [	 ]*vupkzh	%v15,%v17,13
++.*:	e6 f1 00 d0 04 5c [	 ]*vupkzl	%v15,%v17,13
++.*:	b9 3b 00 00 [	 ]*nnpa
++.*:	e6 f1 00 0c d4 56 [	 ]*vclfnh	%v15,%v17,13,12
++.*:	e6 f1 00 0c d4 5e [	 ]*vclfnl	%v15,%v17,13,12
++.*:	e6 f1 40 0c d6 75 [	 ]*vcrnf	%v15,%v17,%v20,13,12
++.*:	e6 f1 00 0c d4 5d [	 ]*vcfn	%v15,%v17,13,12
++.*:	e6 f1 00 0c d4 55 [	 ]*vcnf	%v15,%v17,13,12
++.*:	b9 8b 90 6b [	 ]*rdp	%r6,%r9,%r11
++.*:	b9 8b 9d 6b [	 ]*rdp	%r6,%r9,%r11,13
++.*:	eb 00 68 f0 fd 71 [	 ]*lpswey	-10000\(%r6\)
++.*:	b2 00 6f a0 [	 ]*lbear	4000\(%r6\)
++.*:	b2 01 6f a0 [	 ]*stbear	4000\(%r6\)
++.*:	b2 8f 5f ff [	 ]*qpaci	4095\(%r5\)
++.*:	07 07 [	 ]*nopr	%r7
diff --git a/SOURCES/binutils-undefined-unversioned-symbols.patch b/SOURCES/binutils-undefined-unversioned-symbols.patch
new file mode 100644
index 0000000..e044a5a
--- /dev/null
+++ b/SOURCES/binutils-undefined-unversioned-symbols.patch
@@ -0,0 +1,28 @@
+diff -rup binutils-2.30/bfd/elflink.c binutils.new/bfd/elflink.c
+--- binutils-2.30/bfd/elflink.c	2021-12-09 09:05:54.545468003 +0000
++++ binutils.new/bfd/elflink.c	2021-12-09 09:03:15.366632301 +0000
+@@ -9980,7 +9980,7 @@ elf_link_output_extsym (struct bfd_hash_
+ 	      if (h->verinfo.verdef == NULL
+ 		  || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd)
+ 		      & (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED)))
+-		iversym.vs_vers = 0;
++		iversym.vs_vers = 1;
+ 	      else
+ 		iversym.vs_vers = h->verinfo.verdef->vd_exp_refno + 1;
+ 	    }
+diff -rup binutils-2.30/ld/testsuite/ld-elfvers/vers16.dsym binutils.new/ld/testsuite/ld-elfvers/vers16.dsym
+--- binutils-2.30/ld/testsuite/ld-elfvers/vers16.dsym	2018-01-13 13:31:16.000000000 +0000
++++ binutils.new/ld/testsuite/ld-elfvers/vers16.dsym	2021-12-09 09:05:03.730791511 +0000
+@@ -1,2 +1,2 @@
+ [0-9a-f]+ g +DF (\.text|\.opd|\*ABS\*)	[0-9a-f]+( +Base +)? (0x[0-9a-f]+ )?_?show_bar
+-[0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +(0x[0-9a-f]+ )?_?show_foo
++[0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +Base +(0x[0-9a-f]+ )?_?show_foo
+diff -rup binutils-2.30/ld/testsuite/ld-elfvers/vers6.dsym binutils.new/ld/testsuite/ld-elfvers/vers6.dsym
+--- binutils-2.30/ld/testsuite/ld-elfvers/vers6.dsym	2018-01-13 13:31:16.000000000 +0000
++++ binutils.new/ld/testsuite/ld-elfvers/vers6.dsym	2021-12-09 09:04:45.778917378 +0000
+@@ -1,4 +1,4 @@
+-[0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +(0x[0-9a-f]+ )?_?show_foo
++[0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +Base +(0x[0-9a-f]+ )?_?show_foo
+ [0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +VERS_2.0 +(0x[0-9a-f]+ )?_?show_foo
+ [0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +VERS_1.2 +(0x[0-9a-f]+ )?_?show_foo
+ [0-9a-f]+ +DF \*UND\*	[0-9a-f]+ +VERS_1.1 +(0x[0-9a-f]+ )?_?show_foo
diff --git a/SOURCES/binutils.unicode.patch b/SOURCES/binutils.unicode.patch
new file mode 100644
index 0000000..bbb87c1
--- /dev/null
+++ b/SOURCES/binutils.unicode.patch
@@ -0,0 +1,1932 @@
+diff -rup binutils.orig/binutils/NEWS binutils-2.30/binutils/NEWS
+--- binutils.orig/binutils/NEWS	2021-10-20 12:39:41.715008273 +0100
++++ binutils-2.30/binutils/NEWS	2021-10-20 12:41:30.895327968 +0100
+@@ -1,5 +1,14 @@
+ -*- text -*-
+ 
++* Tools which display names or strings (readelf, strings, nm, objdump)
++  have a new command line option which controls how unicode characters are
++  handled.  By default they are treated as normal for the tool.  Using
++  --unicode=locale will display them according to the current locale.
++  Using --unicode=hex will display them as hex byte values, whilst
++  --unicode=escape will display them as escape sequences.  In addition
++  using --unicode=highlight will display them as unicode escape sequences
++  highlighted in red (if supported by the output device).
++
+ * Add support for disassembling netronome Flow Processor (NFP) firmware files.
+ 
+ Changes in 2.30:
+diff -rup binutils.orig/binutils/doc/binutils.texi binutils-2.30/binutils/doc/binutils.texi
+--- binutils.orig/binutils/doc/binutils.texi	2021-10-20 12:39:41.701008360 +0100
++++ binutils-2.30/binutils/doc/binutils.texi	2021-10-20 13:00:11.801327501 +0100
+@@ -762,6 +762,7 @@ nm [@option{-A}|@option{-o}|@option{--pr
+    [@option{-D}|@option{--dynamic}] [@option{-f}@var{format}|@option{--format=}@var{format}]
+    [@option{-g}|@option{--extern-only}] [@option{-h}|@option{--help}]
+    [@option{-l}|@option{--line-numbers}] [@option{--inlines}]
++   [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
+    [@option{-n}|@option{-v}|@option{--numeric-sort}]
+    [@option{-P}|@option{--portability}] [@option{-p}|@option{--no-sort}]
+    [@option{-r}|@option{--reverse-sort}] [@option{-S}|@option{--print-size}]
+@@ -1026,6 +1027,21 @@ Use @var{radix} as the radix for printin
+ @cindex undefined symbols
+ Display only undefined symbols (those external to each object file).
+ 
++@item -U @var{[d|i|l|e|x|h]}
++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
++Controls the display of UTF-8 encoded mulibyte characters in strings.
++The default (@option{--unicode=default}) is to give them no special
++treatment.  The @option{--unicode=locale} option displays the sequence
++in the current locale, which may or may not support them.  The options
++@option{--unicode=hex} and @option{--unicode=invalid} display them as
++hex byte sequences enclosed by either angle brackets or curly braces.
++
++The @option{--unicode=escape} option displays them as escape sequences
++(@var{\uxxxx}) and the @option{--unicode=highlight} option displays
++them as escape sequences highlighted in red (if supported by the
++output device).  The colouring is intended to draw attention to the
++presence of unicode sequences where they might not be expected.
++
+ @item -V
+ @itemx --version
+ Show the version number of @command{nm} and exit.
+@@ -2093,6 +2109,7 @@ objdump [@option{-a}|@option{--archive-h
+         [@option{--prefix=}@var{prefix}]
+         [@option{--prefix-strip=}@var{level}]
+         [@option{--insn-width=}@var{width}]
++        [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
+         [@option{-V}|@option{--version}]
+         [@option{-H}|@option{--help}]
+         @var{objfile}@dots{}
+@@ -2697,6 +2714,21 @@ When displaying symbols include those wh
+ special in some way and which would not normally be of interest to the
+ user.
+ 
++@item -U @var{[d|i|l|e|x|h]}
++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
++Controls the display of UTF-8 encoded mulibyte characters in strings.
++The default (@option{--unicode=default}) is to give them no special
++treatment.  The @option{--unicode=locale} option displays the sequence
++in the current locale, which may or may not support them.  The options
++@option{--unicode=hex} and @option{--unicode=invalid} display them as
++hex byte sequences enclosed by either angle brackets or curly braces.
++
++The @option{--unicode=escape} option displays them as escape sequences
++(@var{\uxxxx}) and the @option{--unicode=highlight} option displays
++them as escape sequences highlighted in red (if supported by the
++output device).  The colouring is intended to draw attention to the
++presence of unicode sequences where they might not be expected.
++
+ @item -V
+ @itemx --version
+ Print the version number of @command{objdump} and exit.
+@@ -2952,6 +2984,7 @@ strings [@option{-afovV}] [@option{-}@va
+         [@option{-n} @var{min-len}] [@option{--bytes=}@var{min-len}]
+         [@option{-t} @var{radix}] [@option{--radix=}@var{radix}]
+         [@option{-e} @var{encoding}] [@option{--encoding=}@var{encoding}]
++        [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
+         [@option{-}] [@option{--all}] [@option{--print-file-name}]
+         [@option{-T} @var{bfdname}] [@option{--target=}@var{bfdname}]
+         [@option{-w}] [@option{--include-all-whitespace}]
+@@ -3043,6 +3076,28 @@ single-8-bit-byte characters, @samp{b} =
+ littleendian.  Useful for finding wide character strings. (@samp{l}
+ and @samp{b} apply to, for example, Unicode UTF-16/UCS-2 encodings).
+ 
++@item -U @var{[d|i|l|e|x|h]}
++@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
++Controls the display of UTF-8 encoded mulibyte characters in strings.
++The default (@option{--unicode=default}) is to give them no special
++treatment, and instead rely upon the setting of the
++@option{--encoding} option.  The other values for this option
++automatically enable @option{--encoding=S}.
++
++The @option{--unicode=invalid} option treats them as non-graphic
++characters and hence not part of a valid string.  All the remaining
++options treat them as valid string characters.
++
++The @option{--unicode=locale} option displays them in the current
++locale, which may or may not support UTF-8 encoding.  The
++@option{--unicode=hex} option displays them as hex byte sequences
++enclosed between @var{<>} characters.  The @option{--unicode=escape}
++option displays them as escape sequences (@var{\uxxxx}) and the
++@option{--unicode=highlight} option displays them as escape sequences
++highlighted in red (if supported by the output device).  The colouring
++is intended to draw attention to the presence of unicode sequences
++where they might not be expected.
++
+ @item -T @var{bfdname}
+ @itemx --target=@var{bfdname}
+ @cindex object code format
+@@ -4603,6 +4658,7 @@ readelf [@option{-a}|@option{--all}]
+         [@option{-v}|@option{--version}]
+         [@option{-W}|@option{--wide}]
+         [@option{-H}|@option{--help}]
++        [@option{-U} @var{method}|@option{--unicode=}@var{method}]
+         @var{elffile}@dots{}
+ @c man end
+ @end smallexample
+@@ -4692,6 +4748,28 @@ Displays the entries in dynamic symbol t
+ has one.  The output format is the same as the format used by the
+ @option{--syms} option.
+ 
++@item -U @var{[d|i|l|e|x|h]}
++@itemx --unicode=[default|invalid|locale|escape|hex|highlight]
++Controls the display of non-ASCII characters in identifier names.
++The default (@option{--unicode=locale} or @option{--unicode=default}) is
++to treat them as multibyte characters and display them in the current
++locale.  All other versions of this option treat the bytes as UTF-8
++encoded values and attempt to interpret them.  If they cannot be
++interpreted or if the @option{--unicode=invalid} option is used then
++they are displayed as a sequence of hex bytes, encloses in curly
++parethesis characters.
++
++Using the @option{--unicode=escape} option will display the characters
++as as unicode escape sequences (@var{\uxxxx}).  Using the
++@option{--unicode=hex} will display the characters as hex byte
++sequences enclosed between angle brackets.
++
++Using the @option{--unicode=highlight} will display the characters as 
++unicode escape sequences but it will also highlighted them in red,
++assuming that colouring is supported by the output device.  The
++colouring is intended to draw attention to the presence of unicode
++sequences when they might not be expected.
++
+ @item -e
+ @itemx --headers
+ Display all the headers in the file.  Equivalent to @option{-h -l -S}.
+diff -rup binutils.orig/binutils/nm.c binutils-2.30/binutils/nm.c
+--- binutils.orig/binutils/nm.c	2021-10-20 12:39:41.681008485 +0100
++++ binutils-2.30/binutils/nm.c	2021-10-20 12:52:26.731237376 +0100
+@@ -38,6 +38,11 @@
+ #include "bucomm.h"
+ #include "plugin-api.h"
+ #include "plugin.h"
++#include "safe-ctype.h"
++
++#ifndef streq
++#define streq(a,b) (strcmp ((a),(b)) == 0)
++#endif
+ 
+ /* When sorting by size, we use this structure to hold the size and a
+    pointer to the minisymbol.  */
+@@ -194,6 +199,18 @@ static const char *plugin_target = NULL;
+ static bfd *lineno_cache_bfd;
+ static bfd *lineno_cache_rel_bfd;
+ 
++typedef enum unicode_display_type
++{
++  unicode_default = 0,
++  unicode_locale,
++  unicode_escape,
++  unicode_hex,
++  unicode_highlight,
++  unicode_invalid
++} unicode_display_type;
++
++static unicode_display_type unicode_display = unicode_default;
++
+ #define OPTION_TARGET 200
+ #define OPTION_PLUGIN (OPTION_TARGET + 1)
+ #define OPTION_SIZE_SORT (OPTION_PLUGIN + 1)
+@@ -224,6 +241,7 @@ static struct option long_options[] =
+   {"target", required_argument, 0, OPTION_TARGET},
+   {"defined-only", no_argument, &defined_only, 1},
+   {"undefined-only", no_argument, &undefined_only, 1},
++  {"unicode", required_argument, NULL, 'U'},
+   {"version", no_argument, &show_version, 1},
+   {"with-symbol-versions", no_argument, &with_symbol_versions, 1},
+   {0, no_argument, 0, 0}
+@@ -271,6 +289,8 @@ usage (FILE *stream, int status)
+   -t, --radix=RADIX      Use RADIX for printing symbol values\n\
+       --target=BFDNAME   Specify the target object format as BFDNAME\n\
+   -u, --undefined-only   Display only undefined symbols\n\
++  -U {d|s|i|x|e|h}       Specify how to treat UTF-8 encoded unicode characters\n\
++      --unicode={default|show|invalid|hex|escape|highlight}\n\
+       --with-symbol-versions  Display version strings after symbol names\n\
+   -X 32_64               (ignored)\n\
+   @FILE                  Read options from FILE\n\
+@@ -399,6 +419,189 @@ get_coff_symbol_type (const struct inter
+   return bufp;
+ }
+ 
++/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
++   The conversion format is controlled by the unicode_display variable.
++   Returns the number of characters added to OUT.
++   Returns the number of bytes consumed from IN in CONSUMED.
++   Always consumes at least one byte and displays at least one character.  */
++   
++static unsigned int
++display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
++{
++  char *        orig_out = out;
++  unsigned int  nchars = 0;
++
++  if (unicode_display == unicode_default)
++    goto invalid;
++
++  if (in[0] < 0xc0)
++    goto invalid;
++
++  if ((in[1] & 0xc0) != 0x80)
++    goto invalid;
++
++  if ((in[0] & 0x20) == 0)
++    {
++      nchars = 2;
++      goto valid;
++    }
++
++  if ((in[2] & 0xc0) != 0x80)
++    goto invalid;
++
++  if ((in[0] & 0x10) == 0)
++    {
++      nchars = 3;
++      goto valid;
++    }
++
++  if ((in[3] & 0xc0) != 0x80)
++    goto invalid;
++
++  nchars = 4;
++
++ valid:
++  switch (unicode_display)
++    {
++    case unicode_locale:
++      /* Copy the bytes into the output buffer as is.  */
++      memcpy (out, in, nchars);
++      out += nchars;
++      break;
++
++    case unicode_invalid:
++    case unicode_hex:
++      {
++      unsigned int j;
++
++      out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
++      for (j = 0; j < nchars; j++)
++	out += sprintf (out, "%02x", in [j]);
++      out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
++      }
++      break;
++      
++    case unicode_highlight:
++      if (isatty (1))
++	out += sprintf (out, "\x1B[31;47m"); /* Red.  */
++      /* Fall through.  */
++    case unicode_escape:
++      switch (nchars)
++	{
++	case 2:
++	  out += sprintf (out, "\\u%02x%02x",
++		  ((in[0] & 0x1c) >> 2), 
++		  ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
++	  break;
++
++	case 3:
++	  out += sprintf (out, "\\u%02x%02x",
++		  ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
++		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
++	  break;
++
++	case 4:
++	  out += sprintf (out, "\\u%02x%02x%02x",
++		  ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
++		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
++		  ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
++	  break;
++	default:
++	  /* URG.  */
++	  break;
++	}
++
++      if (unicode_display == unicode_highlight && isatty (1))
++	out += sprintf (out, "\033[0m"); /* Default colour.  */
++      break;
++
++    default:
++      /* URG */
++      break;
++    }
++
++  * consumed = nchars;
++  return out - orig_out;
++
++ invalid:
++  /* Not a valid UTF-8 sequence.  */
++  *out = *in;
++  * consumed = 1;
++  return 1;
++}
++
++/* Convert any UTF-8 encoded characters in NAME into the form specified by
++   unicode_display.  Also converts control characters.  Returns a static
++   buffer if conversion was necessary.
++   Code stolen from objdump.c:sanitize_string().  */
++
++static const char *
++convert_utf8 (const char * in)
++{
++  static char *  buffer = NULL;
++  static size_t  buffer_len = 0;
++  const char *   original = in;
++  char *         out;
++
++  /* Paranoia.  */
++  if (in == NULL)
++    return "";
++
++  /* See if any conversion is necessary.
++     In the majority of cases it will not be needed.  */
++  do
++    {
++      unsigned char c = *in++;
++
++      if (c == 0)
++	return original;
++
++      if (ISCNTRL (c))
++	break;
++
++      if (unicode_display != unicode_default && c >= 0xc0)
++	break;
++    }
++  while (1);
++
++  /* Copy the input, translating as needed.  */
++  in = original;
++  if (buffer_len < (strlen (in) * 9))
++    {
++      free ((void *) buffer);
++      buffer_len = strlen (in) * 9;
++      buffer = xmalloc (buffer_len + 1);
++    }
++
++  out = buffer;
++  do
++    {
++      unsigned char c = *in++;
++
++      if (c == 0)
++	break;
++
++      if (ISCNTRL (c))
++	{
++	  *out++ = '^';
++	  *out++ = c + 0x40;
++	}
++      else if (unicode_display != unicode_default && c >= 0xc0)
++	{
++	  unsigned int num_consumed;
++
++	  out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
++	  in += num_consumed - 1;
++	}
++      else
++	*out++ = c;
++    }
++  while (1);
++
++  *out = 0;
++  return buffer;
++}
++
+ /* Print symbol name NAME, read from ABFD, with printf format FORM,
+    demangling it if requested.  */
+ 
+@@ -417,6 +618,9 @@ print_symname (const char *form, const c
+ 	}
+     }
+ 
++  if (unicode_display != unicode_default)
++    name = convert_utf8 (name);
++
+   printf (form, name);
+ }
+ 
+@@ -1657,7 +1861,7 @@ main (int argc, char **argv)
+   bfd_init ();
+   set_default_bfd_target ();
+ 
+-  while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
++  while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uU:vVvX:",
+ 			   long_options, (int *) 0)) != EOF)
+     {
+       switch (c)
+@@ -1738,6 +1942,24 @@ main (int argc, char **argv)
+ 	case 'u':
+ 	  undefined_only = 1;
+ 	  break;
++
++	case 'U':
++	  if (streq (optarg, "default") || streq (optarg, "d"))
++	    unicode_display = unicode_default;
++	  else if (streq (optarg, "locale") || streq (optarg, "l"))
++	    unicode_display = unicode_locale;
++	  else if (streq (optarg, "escape") || streq (optarg, "e"))
++	    unicode_display = unicode_escape;
++	  else if (streq (optarg, "invalid") || streq (optarg, "i"))
++	    unicode_display = unicode_invalid;
++	  else if (streq (optarg, "hex") || streq (optarg, "x"))
++	    unicode_display = unicode_hex;
++	  else if (streq (optarg, "highlight") || streq (optarg, "h"))
++	    unicode_display = unicode_highlight;
++	  else
++	    fatal (_("invalid argument to -U/--unicode: %s"), optarg);
++	  break;
++
+ 	case 'V':
+ 	  show_version = 1;
+ 	  break;
+diff -rup binutils.orig/binutils/objdump.c binutils-2.30/binutils/objdump.c
+--- binutils.orig/binutils/objdump.c	2021-10-20 12:39:41.677008510 +0100
++++ binutils-2.30/binutils/objdump.c	2021-10-20 13:24:11.009293189 +0100
+@@ -192,6 +192,18 @@ static const struct objdump_private_desc
+     OBJDUMP_PRIVATE_VECTORS
+     NULL
+   };
++
++typedef enum unicode_display_type
++{
++  unicode_default = 0,
++  unicode_locale,
++  unicode_escape,
++  unicode_hex,
++  unicode_highlight,
++  unicode_invalid
++} unicode_display_type;
++
++static unicode_display_type unicode_display = unicode_default;
+ 
+ static void usage (FILE *, int) ATTRIBUTE_NORETURN;
+ static void
+@@ -225,6 +237,9 @@ usage (FILE *stream, int status)
+   -r, --reloc              Display the relocation entries in the file\n\
+   -R, --dynamic-reloc      Display the dynamic relocation entries in the file\n\
+   @<file>                  Read options from <file>\n\
++  -U[d|l|i|x|e|h]          Controls the display of UTF-8 unicode characters\n\
++  --unicode=[default|locale|invalid|hex|escape|highlight]\n"));
++      fprintf (stream, _("\
+   -v, --version            Display this program's version number\n\
+   -i, --info               List object formats and architectures supported\n\
+   -H, --help               Display this information\n\
+@@ -343,6 +358,7 @@ static struct option long_options[]=
+   {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
+   {"syms", no_argument, NULL, 't'},
+   {"target", required_argument, NULL, 'b'},
++  {"unicode", required_argument, NULL, 'U'},
+   {"version", no_argument, NULL, 'V'},
+   {"wide", no_argument, NULL, 'w'},
+   {"prefix", required_argument, NULL, OPTION_PREFIX},
+@@ -362,6 +378,191 @@ nonfatal (const char *msg)
+   exit_status = 1;
+ }
+ 
++/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
++   The conversion format is controlled by the unicode_display variable.
++   Returns the number of characters added to OUT.
++   Returns the number of bytes consumed from IN in CONSUMED.
++   Always consumes at least one byte and displays at least one character.  */
++   
++static unsigned int
++display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
++{
++  char *        orig_out = out;
++  unsigned int  nchars = 0;
++
++  if (unicode_display == unicode_default)
++    goto invalid;
++
++  if (in[0] < 0xc0)
++    goto invalid;
++
++  if ((in[1] & 0xc0) != 0x80)
++    goto invalid;
++
++  if ((in[0] & 0x20) == 0)
++    {
++      nchars = 2;
++      goto valid;
++    }
++
++  if ((in[2] & 0xc0) != 0x80)
++    goto invalid;
++
++  if ((in[0] & 0x10) == 0)
++    {
++      nchars = 3;
++      goto valid;
++    }
++
++  if ((in[3] & 0xc0) != 0x80)
++    goto invalid;
++
++  nchars = 4;
++
++ valid:
++  switch (unicode_display)
++    {
++    case unicode_locale:
++      /* Copy the bytes into the output buffer as is.  */
++      memcpy (out, in, nchars);
++      out += nchars;
++      break;
++
++    case unicode_invalid:
++    case unicode_hex:
++      {
++      unsigned int j;
++
++      out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
++      for (j = 0; j < nchars; j++)
++	out += sprintf (out, "%02x", in [j]);
++      out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
++      }
++      break;
++      
++    case unicode_highlight:
++      if (isatty (1))
++	out += sprintf (out, "\x1B[31;47m"); /* Red.  */
++      /* Fall through.  */
++    case unicode_escape:
++      switch (nchars)
++	{
++	case 2:
++	  out += sprintf (out, "\\u%02x%02x",
++		  ((in[0] & 0x1c) >> 2), 
++		  ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
++	  break;
++
++	case 3:
++	  out += sprintf (out, "\\u%02x%02x",
++		  ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
++		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
++	  break;
++
++	case 4:
++	  out += sprintf (out, "\\u%02x%02x%02x",
++		  ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
++		  ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
++		  ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
++	  break;
++	default:
++	  /* URG.  */
++	  break;
++	}
++
++      if (unicode_display == unicode_highlight && isatty (1))
++	out += sprintf (out, "\033[0m"); /* Default colour.  */
++      break;
++
++    default:
++      /* URG */
++      break;
++    }
++
++  * consumed = nchars;
++  return out - orig_out;
++
++ invalid:
++  /* Not a valid UTF-8 sequence.  */
++  *out = *in;
++  * consumed = 1;
++  return 1;
++}
++
++/* Returns a version of IN with any control characters
++   replaced by escape sequences.  Uses a static buffer
++   if necessary.
++
++   If unicode display is enabled, then also handles the
++   conversion of unicode characters.  */
++
++static const char *
++sanitize_string (const char * in)
++{
++  static char *  buffer = NULL;
++  static size_t  buffer_len = 0;
++  const char *   original = in;
++  char *         out;
++
++  /* Paranoia.  */
++  if (in == NULL)
++    return "";
++
++  /* See if any conversion is necessary.  In the majority
++     of cases it will not be needed.  */
++  do
++    {
++      unsigned char c = *in++;
++
++      if (c == 0)
++	return original;
++
++      if (ISCNTRL (c))
++	break;
++
++      if (unicode_display != unicode_default && c >= 0xc0)
++	break;
++    }
++  while (1);
++
++  /* Copy the input, translating as needed.  */
++  in = original;
++  if (buffer_len < (strlen (in) * 9))
++    {
++      free ((void *) buffer);
++      buffer_len = strlen (in) * 9;
++      buffer = xmalloc (buffer_len + 1);
++    }
++
++  out = buffer;
++  do
++    {
++      unsigned char c = *in++;
++
++      if (c == 0)
++	break;
++
++      if (ISCNTRL (c))
++	{
++	  *out++ = '^';
++	  *out++ = c + 0x40;
++	}
++      else if (unicode_display != unicode_default && c >= 0xc0)
++	{
++	  unsigned int num_consumed;
++
++	  out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
++	  in += num_consumed - 1;
++	}
++      else
++	*out++ = c;
++    }
++  while (1);
++
++  *out = 0;
++  return buffer;
++}
++
+ /* Returns TRUE if the specified section should be dumped.  */
+ 
+ static bfd_boolean
+@@ -458,8 +657,8 @@ dump_section_header (bfd *abfd, asection
+     return;
+ 
+   printf ("%3d %-*s %08lx  ", section->index, longest_section_name,
+-	  bfd_get_section_name (abfd, section),
+-	  (unsigned long) bfd_section_size (abfd, section) / opb);
++	  sanitize_string (bfd_section_name (abfd, section)),
++	  (unsigned long) bfd_section_size (abfd, section) / opb);
+   bfd_printf_vma (abfd, bfd_get_section_vma (abfd, section));
+   printf ("  ");
+   bfd_printf_vma (abfd, section->lma);
+@@ -892,6 +1091,8 @@ objdump_print_symname (bfd *abfd, struct
+   if (bfd_is_und_section (bfd_get_section (sym)))
+     hidden = TRUE;
+ 
++  name = sanitize_string (name);
++
+   if (inf != NULL)
+     {
+       (*inf->fprintf_func) (inf->stream, "%s", name);
+@@ -1141,7 +1342,7 @@ objdump_print_addr_with_sym (bfd *abfd,
+       bfd_vma secaddr;
+ 
+       (*inf->fprintf_func) (inf->stream, " <%s",
+-			    bfd_get_section_name (abfd, sec));
++			    sanitize_string (bfd_section_name (abfd, sec)));
+       secaddr = bfd_get_section_vma (abfd, sec);
+       if (vma < secaddr)
+ 	{
+@@ -1563,7 +1764,7 @@ show_line (bfd *abfd, asection *section,
+ 	  && (prev_functionname == NULL
+ 	      || strcmp (functionname, prev_functionname) != 0))
+ 	{
+-	  printf ("%s():\n", functionname);
++	  printf ("%s():\n", sanitize_string (functionname));
+ 	  prev_line = -1;
+ 	}
+       if (linenumber > 0
+@@ -1572,10 +1773,10 @@ show_line (bfd *abfd, asection *section,
+ 	{
+ 	  if (discriminator > 0)
+ 	    printf ("%s:%u (discriminator %u)\n",
+-		    filename == NULL ? "???" : filename,
++		    filename == NULL ? "???" : sanitize_string (filename),
+ 		    linenumber, discriminator);
+ 	  else
+-	    printf ("%s:%u\n", filename == NULL ? "???" : filename,
++	    printf ("%s:%u\n", filename == NULL ? "???" : sanitize_string (filename),
+ 		    linenumber);
+ 	}
+       if (unwind_inlines)
+@@ -1586,8 +1787,10 @@ show_line (bfd *abfd, asection *section,
+ 
+ 	  while (bfd_find_inliner_info (abfd, &filename2, &functionname2,
+ 					&line2))
+-	    printf ("inlined by %s:%u (%s)\n", filename2, line2,
+-		    functionname2);
++	    {
++	      printf ("inlined by %s:%u", sanitize_string (filename2), line2);
++	      printf (" (%s)\n", sanitize_string (functionname2));
++	    }
+ 	}
+     }
+ 
+@@ -2081,7 +2284,7 @@ disassemble_bytes (struct disassemble_in
+ 		      sym_name = bfd_get_section_name (aux->abfd, sym_sec);
+ 		      if (sym_name == NULL || *sym_name == '\0')
+ 			sym_name = "*unknown*";
+-		      printf ("%s", sym_name);
++		      printf ("%s", sanitize_string (sym_name));
+ 		    }
+ 		}
+ 
+@@ -2228,7 +2431,7 @@ disassemble_section (bfd *abfd, asection
+ 	 && (*rel_pp)->address < rel_offset + addr_offset)
+     ++rel_pp;
+ 
+-  printf (_("\nDisassembly of section %s:\n"), section->name);
++  printf (_("\nDisassembly of section %s:\n"), sanitize_string (section->name));
+ 
+   /* Find the nearest symbol forwards from our current position.  */
+   paux->require_sec = TRUE;
+@@ -2512,7 +2715,7 @@ load_specific_debug_section (enum dwarf_
+     {
+       free_debug_section (debug);
+       printf (_("\nCan't get contents for section '%s'.\n"),
+-	      section->name);
++	      sanitize_string (section->name));
+       return FALSE;
+     }
+   /* Ensure any string section has a terminating NUL.  */
+@@ -2534,7 +2737,7 @@ load_specific_debug_section (enum dwarf_
+         {
+           free_debug_section (debug);
+           printf (_("\nCan't get contents for section '%s'.\n"),
+-	          section->name);
++	          sanitize_string (section->name));
+           return FALSE;
+         }
+ 
+@@ -2780,14 +2983,14 @@ read_section_stabs (bfd *abfd, const cha
+   stabsect = bfd_get_section_by_name (abfd, sect_name);
+   if (stabsect == NULL)
+     {
+-      printf (_("No %s section present\n\n"), sect_name);
++      printf (_("No %s section present\n\n"), sanitize_string (sect_name));
+       return FALSE;
+     }
+ 
+   if (!bfd_malloc_and_get_section (abfd, stabsect, &contents))
+     {
+       non_fatal (_("reading %s section of %s failed: %s"),
+-		 sect_name, bfd_get_filename (abfd),
++		 sanitize_string (sect_name), bfd_get_filename (abfd),
+ 		 bfd_errmsg (bfd_get_error ()));
+       exit_status = 1;
+       free (contents);
+@@ -2830,7 +3033,7 @@ print_section_stabs (bfd *abfd,
+   stabp = stabs;
+   stabs_end = stabp + stab_size;
+ 
+-  printf (_("Contents of %s section:\n\n"), stabsect_name);
++  printf (_("Contents of %s section:\n\n"), sanitize_string (stabsect_name));
+   printf ("Symnum n_type n_othr n_desc n_value  n_strx String\n");
+ 
+   /* Loop through all symbols and print them.
+@@ -3093,7 +3296,7 @@ dump_section (bfd *abfd, asection *secti
+   if (start_offset >= stop_offset)
+     return;
+ 
+-  printf (_("Contents of section %s:"), section->name);
++  printf (_("Contents of section %s:"), sanitize_string (section->name));
+   if (display_file_offsets)
+     printf (_("  (Starting at file offset: 0x%lx)"),
+ 	    (unsigned long) (section->filepos + start_offset));
+@@ -3102,7 +3305,7 @@ dump_section (bfd *abfd, asection *secti
+   if (!bfd_get_full_section_contents (abfd, section, &data))
+     {
+       non_fatal (_("Reading section %s failed because: %s"),
+-		 section->name, bfd_errmsg (bfd_get_error ()));
++		 sanitize_string (section->name), bfd_errmsg (bfd_get_error ()));
+       return;
+     }
+ 
+@@ -3242,6 +3445,24 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED
+ 		  free (alloc);
+ 		}
+ 	    }
++	  else if (unicode_display != unicode_default
++		   && name != NULL && *name != '\0')
++	    {
++	      const char * sanitized_name;
++
++	      /* If we want to sanitize the name, we do it here, and
++		 temporarily clobber it while calling bfd_print_symbol.
++		 FIXME: This is a gross hack.  */
++	      sanitized_name = sanitize_string (name);
++	      if (sanitized_name != name)
++		(*current)->name = sanitized_name;
++	      else
++		sanitized_name = NULL;
++	      bfd_print_symbol (cur_bfd, stdout, *current,
++				bfd_print_symbol_all);
++	      if (sanitized_name != NULL)
++		(*current)->name = name;
++	    }
+ 	  else
+ 	    bfd_print_symbol (cur_bfd, stdout, *current,
+ 			      bfd_print_symbol_all);
+@@ -3307,7 +3528,7 @@ dump_reloc_set (bfd *abfd, asection *sec
+ 	      && (last_functionname == NULL
+ 		  || strcmp (functionname, last_functionname) != 0))
+ 	    {
+-	      printf ("%s():\n", functionname);
++	      printf ("%s():\n", sanitize_string (functionname));
+ 	      if (last_functionname != NULL)
+ 		free (last_functionname);
+ 	      last_functionname = xstrdup (functionname);
+@@ -3321,9 +3542,9 @@ dump_reloc_set (bfd *abfd, asection *sec
+                   || (discriminator != last_discriminator)))
+ 	    {
+               if (discriminator > 0)
+-                printf ("%s:%u\n", filename == NULL ? "???" : filename, linenumber);
++                printf ("%s:%u\n", filename == NULL ? "???" : sanitize_string (filename), linenumber);
+               else
+-                printf ("%s:%u (discriminator %u)\n", filename == NULL ? "???" : filename,
++                printf ("%s:%u (discriminator %u)\n", filename == NULL ? "???" : sanitize_string (filename),
+                         linenumber, discriminator);
+ 	      last_line = linenumber;
+ 	      last_discriminator = discriminator;
+@@ -3393,7 +3614,7 @@ dump_reloc_set (bfd *abfd, asection *sec
+ 	{
+ 	  if (section_name == NULL)
+ 	    section_name = "*unknown*";
+-	  printf ("[%s]", section_name);
++	  printf ("[%s]", sanitize_string (section_name));
+ 	}
+ 
+       if (q->addend)
+@@ -3443,7 +3664,7 @@ dump_relocs_in_section (bfd *abfd,
+   if (relsize < 0)
+     bfd_fatal (bfd_get_filename (abfd));
+ 
+-  printf ("RELOCATION RECORDS FOR [%s]:", section->name);
++  printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name));
+ 
+   if (relsize == 0)
+     {
+@@ -3835,7 +4056,7 @@ main (int argc, char **argv)
+   set_default_bfd_target ();
+ 
+   while ((c = getopt_long (argc, argv,
+-			   "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
++			   "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::U:",
+ 			   long_options, (int *) 0))
+ 	 != EOF)
+     {
+@@ -4069,6 +4290,23 @@ main (int argc, char **argv)
+ 	  seenflag = TRUE;
+ 	  break;
+ 
++	case 'U':
++	  if (streq (optarg, "default") || streq (optarg, "d"))
++	    unicode_display = unicode_default;
++	  else if (streq (optarg, "locale") || streq (optarg, "l"))
++	    unicode_display = unicode_locale;
++	  else if (streq (optarg, "escape") || streq (optarg, "e"))
++	    unicode_display = unicode_escape;
++	  else if (streq (optarg, "invalid") || streq (optarg, "i"))
++	    unicode_display = unicode_invalid;
++	  else if (streq (optarg, "hex") || streq (optarg, "x"))
++	    unicode_display = unicode_hex;
++	  else if (streq (optarg, "highlight") || streq (optarg, "h"))
++	    unicode_display = unicode_highlight;
++	  else
++	    fatal (_("invalid argument to -U/--unicode: %s"), optarg);
++	  break;
++
+ 	case 'H':
+ 	  usage (stdout, 0);
+ 	  /* No need to set seenflag or to break - usage() does not return.  */
+diff -rup binutils.orig/binutils/strings.c binutils-2.30/binutils/strings.c
+--- binutils.orig/binutils/strings.c	2021-10-20 12:39:41.686008454 +0100
++++ binutils-2.30/binutils/strings.c	2021-10-20 13:32:22.029182908 +0100
+@@ -55,6 +55,19 @@
+    -T {bfdname}
+ 		Specify a non-default object file format.
+ 
++  --unicode={default|locale|invalid|hex|escape|highlight}
++  -U {d|l|i|x|e|h}
++                Determine how to handle UTF-8 unicode characters.  The default
++		is no special treatment.  All other versions of this option
++		only apply if the encoding is valid and enabling the option
++		implies --encoding=S.
++		The 'locale' option displays the characters according to the
++		current locale.  The 'invalid' option treats them as
++		non-string characters.  The 'hex' option displays them as hex
++		byte sequences.  The 'escape' option displays them as escape
++		sequences and the 'highlight' option displays them as
++		coloured escape sequences.
++
+   --output-separator=sep_string
+   -s sep_string	String used to separate parsed strings in output.
+ 		Default is newline.
+@@ -76,6 +89,22 @@
+ #include "safe-ctype.h"
+ #include "bucomm.h"
+ 
++#ifndef streq
++#define streq(a,b) (strcmp ((a),(b)) == 0)
++#endif
++
++typedef enum unicode_display_type
++{
++  unicode_default = 0,
++  unicode_locale,
++  unicode_escape,
++  unicode_hex,
++  unicode_highlight,
++  unicode_invalid
++} unicode_display_type;
++
++static unicode_display_type unicode_display = unicode_default;
++
+ #define STRING_ISGRAPHIC(c) \
+       (   (c) >= 0 \
+        && (c) <= 255 \
+@@ -94,7 +123,7 @@ extern int errno;
+ static int address_radix;
+ 
+ /* Minimum length of sequence of graphic chars to trigger output.  */
+-static int string_min;
++static uint string_min;
+ 
+ /* Whether or not we include all whitespace as a graphic char.   */
+ static bfd_boolean include_all_whitespace;
+@@ -130,6 +159,7 @@ static struct option long_options[] =
+   {"target", required_argument, NULL, 'T'},
+   {"output-separator", required_argument, NULL, 's'},
+   {"help", no_argument, NULL, 'h'},
++  {"unicode", required_argument, NULL, 'U'},
+   {"version", no_argument, NULL, 'v'},
+   {NULL, 0, NULL, 0}
+ };
+@@ -173,7 +203,7 @@ main (int argc, char **argv)
+   encoding = 's';
+   output_separator = NULL;
+ 
+-  while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
++  while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:U:Vv0123456789",
+ 			      long_options, (int *) 0)) != EOF)
+     {
+       switch (optc)
+@@ -246,6 +276,23 @@ main (int argc, char **argv)
+ 	  output_separator = optarg;
+           break;
+ 
++	case 'U':
++	  if (streq (optarg, "default") || streq (optarg, "d"))
++	    unicode_display = unicode_default;
++	  else if (streq (optarg, "locale") || streq (optarg, "l"))
++	    unicode_display = unicode_locale;
++	  else if (streq (optarg, "escape") || streq (optarg, "e"))
++	    unicode_display = unicode_escape;
++	  else if (streq (optarg, "invalid") || streq (optarg, "i"))
++	    unicode_display = unicode_invalid;
++	  else if (streq (optarg, "hex") || streq (optarg, "x"))
++	    unicode_display = unicode_hex;
++	  else if (streq (optarg, "highlight") || streq (optarg, "h"))
++	    unicode_display = unicode_highlight;
++	  else
++	    fatal (_("invalid argument to -U/--unicode: %s"), optarg);
++	  break;
++
+ 	case 'V':
+ 	case 'v':
+ 	  print_version ("strings");
+@@ -260,6 +307,9 @@ main (int argc, char **argv)
+ 	}
+     }
+ 
++  if (unicode_display != unicode_default)
++    encoding = 'S';
++
+   if (numeric_opt != 0)
+     {
+       string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
+@@ -501,11 +551,629 @@ get_char (FILE *stream, file_ptr *addres
+ 
+   return r;
+ }
++
++static void
++print_filename_and_address (const char * filename, file_ptr address)
++{
++  if (print_filenames)
++    printf ("%s: ", filename);
++
++  if (! print_addresses)
++    return;
++
++  switch (address_radix)
++    {
++    case 8:
++      if (sizeof (address) > sizeof (long))
++	{
++#ifndef __MSVCRT__
++	  printf ("%7llo ", (unsigned long long) address);
++#else
++	  printf ("%7I64o ", (unsigned long long) address);
++#endif
++	}
++      else
++	printf ("%7lo ", (unsigned long) address);
++      break;
++
++    case 10:
++      if (sizeof (address) > sizeof (long))
++	{
++#ifndef __MSVCRT__
++	  printf ("%7llu ", (unsigned long long) address);
++#else
++	  printf ("%7I64d ", (unsigned long long) address);
++#endif
++	}
++      else
++	printf ("%7ld ", (long) address);
++      break;
++
++    case 16:
++      if (sizeof (address) > sizeof (long))
++	{
++#ifndef __MSVCRT__
++	  printf ("%7llx ", (unsigned long long) address);
++#else
++	  printf ("%7I64x ", (unsigned long long) address);
++#endif
++	}
++      else
++	printf ("%7lx ", (unsigned long) address);
++      break;
++    }
++}
++
++/* Return non-zero if the bytes starting at BUFFER form a valid UTF-8 encoding.
++   If the encoding is valid then returns the number of bytes it uses.  */
++
++static unsigned int
++is_valid_utf8 (const unsigned char * buffer, unsigned long buflen)
++{
++  if (buffer[0] < 0xc0)
++    return 0;
++
++  if (buflen < 2)
++    return 0;
++
++  if ((buffer[1] & 0xc0) != 0x80)
++    return 0;
++
++  if ((buffer[0] & 0x20) == 0)
++    return 2;
++
++  if (buflen < 3)
++    return 0;
++
++  if ((buffer[2] & 0xc0) != 0x80)
++    return 0;
++  
++  if ((buffer[0] & 0x10) == 0)
++    return 3;
++
++  if (buflen < 4)
++    return 0;
++
++  if ((buffer[3] & 0xc0) != 0x80)
++    return 0;
++
++  return 4;
++}
++
++/* Display a UTF-8 encoded character in BUFFER according to the setting
++   of unicode_display.  The character is known to be valid.
++   Returns the number of bytes consumed.  */
++
++static unsigned int
++display_utf8_char (const unsigned char * buffer)
++{
++  unsigned int j;
++  unsigned int utf8_len;
++
++  switch (buffer[0] & 0x30)
++    {
++    case 0x00:
++    case 0x10:
++      utf8_len = 2;
++      break;
++    case 0x20:
++      utf8_len = 3;
++      break;
++    default:
++      utf8_len = 4;
++    }
++      
++  switch (unicode_display)
++    {
++    default:
++      fprintf (stderr, "ICE: unexpected unicode display type\n");
++      break;
++
++    case unicode_escape:
++    case unicode_highlight:
++      if (unicode_display == unicode_highlight && isatty (1))
++	printf ("\x1B[31;47m"); /* Red.  */
++
++      switch (utf8_len)
++	{
++	case 2:
++	  printf ("\\u%02x%02x",
++		  ((buffer[0] & 0x1c) >> 2), 
++		  ((buffer[0] & 0x03) << 6) | (buffer[1] & 0x3f));
++	  break;
++
++	case 3:
++	  printf ("\\u%02x%02x",
++		  ((buffer[0] & 0x0f) << 4) | ((buffer[1] & 0x3c) >> 2),
++		  ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3f)));
++	  break;
++
++	case 4:
++	  printf ("\\u%02x%02x%02x",
++		  ((buffer[0] & 0x07) << 6) | ((buffer[1] & 0x3c) >> 2),
++		  ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3c) >> 2),
++		  ((buffer[2] & 0x03) << 6) | ((buffer[3] & 0x3f)));
++	  break;
++	default:
++	  /* URG.  */
++	  break;
++	}
++
++      if (unicode_display == unicode_highlight && isatty (1))
++	printf ("\033[0m"); /* Default colour.  */
++      break;
++
++    case unicode_hex:
++      putchar ('<');
++      for (j = 0; j < utf8_len; j++)
++	printf ("%02x", buffer [j]);
++      putchar ('>');
++      break;
++
++    case unicode_locale:
++      printf ("%.1s", buffer);
++      break;
++    }
++
++  return utf8_len;
++}
++
++/* Display strings in BUFFER.  Treat any UTF-8 encoded characters encountered
++   according to the setting of the unicode_display variable.  The buffer
++   contains BUFLEN bytes.
++
++   Display the characters as if they started at ADDRESS and are contained in
++   FILENAME.  */
++
++static void
++print_unicode_buffer (const char *            filename,
++		      file_ptr                address,
++		      const unsigned char *   buffer,
++		      unsigned long           buflen)
++{
++  /* Paranoia checks...  */
++  if (filename == NULL
++      || buffer == NULL
++      || unicode_display == unicode_default
++      || encoding != 'S'
++      || encoding_bytes != 1)
++    {
++      fprintf (stderr, "ICE: bad arguments to print_unicode_buffer\n");
++      return;
++    }
++
++  if (buflen == 0)
++    return;
++
++  /* We must only display strings that are at least string_min *characters*
++     long.  So we scan the buffer in two stages.  First we locate the start
++     of a potential string.  Then we walk along it until we have found
++     string_min characters.  Then we go back to the start point and start
++     displaying characters according to the unicode_display setting.  */
++
++  unsigned long start_point = 0;
++  unsigned long i = 0;
++  unsigned int char_len = 1;
++  unsigned int num_found = 0;
++
++  for (i = 0; i < buflen; i += char_len)
++    {
++      int c = buffer[i];
++
++      char_len = 1;
++
++      /* Find the first potential character of a string.  */
++      if (! STRING_ISGRAPHIC (c))
++	{
++	  num_found = 0;
++	  continue;
++	}
++
++      if (c > 126)
++	{
++	  if (c < 0xc0)
++	    {
++	      num_found = 0;
++	      continue;
++	    }
++
++	  if ((char_len = is_valid_utf8 (buffer + i, buflen - i)) == 0)
++	    {
++	      char_len = 1;
++	      num_found = 0;
++	      continue;
++	    }
++
++	  if (unicode_display == unicode_invalid)
++	    {
++	      /* We have found a valid UTF-8 character, but we treat it as non-graphic.  */
++	      num_found = 0;
++	      continue;
++	    }
++	}
++
++      if (num_found == 0)
++	/* We have found a potential starting point for a string.  */
++	start_point = i;
++
++      ++ num_found;
++
++      if (num_found >= string_min)
++	break;
++    }
++
++  if (num_found < string_min)
++    return;
++
++  print_filename_and_address (filename, address + start_point);
++  
++  /* We have found string_min characters.  Display them and any
++     more that follow.  */
++  for (i = start_point; i < buflen; i += char_len)
++    {
++      int c = buffer[i];
++
++      char_len = 1;
++
++      if (! STRING_ISGRAPHIC (c))
++	break;
++      else if (c < 127)
++	putchar (c);
++      else if (! is_valid_utf8 (buffer + i, buflen - i))
++	break;
++      else if (unicode_display == unicode_invalid)
++	break;
++      else
++	char_len = display_utf8_char (buffer + i);
++    }
++
++  if (output_separator)
++    fputs (output_separator, stdout);
++  else
++    putchar ('\n');
++
++  /* FIXME: Using tail recursion here is lazy programming...  */
++  print_unicode_buffer (filename, address + i, buffer + i, buflen - i);
++}
++
++static int
++get_unicode_byte (FILE *           stream,
++		  unsigned char *  putback,
++		  unsigned int *   num_putback,
++		  unsigned int *   num_read)
++{
++  if (* num_putback > 0)
++    {
++      * num_putback = * num_putback - 1;
++      return putback [* num_putback];
++    }
++
++  * num_read = * num_read + 1;
++
++#if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
++  return getc_unlocked (stream);
++#else
++  return getc (stream);
++#endif
++}
++
++/* Helper function for print_unicode_stream.  */
++
++static void
++print_unicode_stream_body (const char *     filename,
++			   file_ptr         address,
++			   FILE *           stream,
++			   unsigned char *  putback_buf,
++			   unsigned int     num_putback,
++			   unsigned char *  print_buf)
++{
++  /* It would be nice if we could just read the stream into a buffer
++     and then process if with print_unicode_buffer.  But the input
++     might be huge or it might time-locked (eg stdin).  So instead
++     we go one byte at a time...  */
++
++  file_ptr start_point = 0;
++  unsigned int num_read = 0;
++  unsigned int num_chars = 0;
++  unsigned int num_print = 0;
++  int c;
++
++  /* Find a series of string_min characters.  Put them into print_buf.  */
++  do
++    {
++      if (num_chars >= string_min)
++	break;
++
++      c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++      if (c == EOF)
++	break;
++
++      if (! STRING_ISGRAPHIC (c))
++	{
++	  num_chars = num_print = 0;
++	  continue;
++	}
++
++      if (num_chars == 0)
++	start_point = num_read - 1;
++
++      if (c < 127)
++	{
++	  print_buf[num_print] = c;
++	  num_chars ++;
++	  num_print ++;
++	  continue;
++	}
++
++      if (c < 0xc0)
++	{
++	  num_chars = num_print = 0;
++	  continue;
++	}
++
++      /* We *might* have a UTF-8 sequence.  Time to start peeking.  */
++      char utf8[4];
++
++      utf8[0] = c;
++      c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++      if (c == EOF)
++	break;
++      utf8[1] = c;
++
++      if ((utf8[1] & 0xc0) != 0x80)
++	{
++	  /* Invalid UTF-8.  */
++	  putback_buf[num_putback++] = utf8[1];
++	  num_chars = num_print = 0;
++	  continue;
++	}
++      else if ((utf8[0] & 0x20) == 0)
++	{
++	  /* A valid 2-byte UTF-8 encoding.  */
++	  if (unicode_display == unicode_invalid)
++	    {
++	      putback_buf[num_putback++] = utf8[1];
++	      num_chars = num_print = 0;
++	    }
++	  else
++	    {
++	      print_buf[num_print ++] = utf8[0];
++	      print_buf[num_print ++] = utf8[1];
++	      num_chars ++;
++	    }
++	  continue;
++	}
++
++      c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++      if (c == EOF)
++	break;
++      utf8[2] = c;
++
++      if ((utf8[2] & 0xc0) != 0x80)
++	{
++	  /* Invalid UTF-8.  */
++	  putback_buf[num_putback++] = utf8[2];
++	  putback_buf[num_putback++] = utf8[1];
++	  num_chars = num_print = 0;
++	  continue;
++	}
++      else if ((utf8[0] & 0x10) == 0)
++	{
++	  /* A valid 3-byte UTF-8 encoding.  */
++	  if (unicode_display == unicode_invalid)
++	    {
++	      putback_buf[num_putback++] = utf8[2];
++	      putback_buf[num_putback++] = utf8[1];
++	      num_chars = num_print = 0;
++	    }
++	  else
++	    {
++	      print_buf[num_print ++] = utf8[0];
++	      print_buf[num_print ++] = utf8[1];
++	      print_buf[num_print ++] = utf8[2];
++	      num_chars ++;
++	    }
++	  continue;
++	}
++
++      c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++      if (c == EOF)
++	break;
++      utf8[3] = c;
++
++      if ((utf8[3] & 0xc0) != 0x80)
++	{
++	  /* Invalid UTF-8.  */
++	  putback_buf[num_putback++] = utf8[3];
++	  putback_buf[num_putback++] = utf8[2];
++	  putback_buf[num_putback++] = utf8[1];
++	  num_chars = num_print = 0;
++	}
++      /* We have a valid 4-byte UTF-8 encoding.  */
++      else if (unicode_display == unicode_invalid)
++	{
++	  putback_buf[num_putback++] = utf8[3];
++	  putback_buf[num_putback++] = utf8[1];
++	  putback_buf[num_putback++] = utf8[2];
++	  num_chars = num_print = 0;
++	}
++      else
++	{
++	  print_buf[num_print ++] = utf8[0];
++	  print_buf[num_print ++] = utf8[1];
++	  print_buf[num_print ++] = utf8[2];
++	  print_buf[num_print ++] = utf8[3];
++	  num_chars ++;
++	}
++    }
++  while (1);
++
++  if (num_chars >= string_min)
++    {
++      /* We know that we have string_min valid characters in print_buf,
++	 and there may be more to come in the stream.  Start displaying
++	 them.  */
++
++      print_filename_and_address (filename, address + start_point);
++
++      unsigned int i;
++      for (i = 0; i < num_print;)
++	{
++	  if (print_buf[i] < 127)
++	    putchar (print_buf[i++]);
++	  else
++	    i += display_utf8_char (print_buf + i);
++	}
++
++      /* OK so now we have to start read unchecked bytes.  */
++
++        /* Find a series of string_min characters.  Put them into print_buf.  */
++      do
++	{
++	  c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++	  if (c == EOF)
++	    break;
++
++	  if (! STRING_ISGRAPHIC (c))
++	    break;
++
++	  if (c < 127)
++	    {
++	      putchar (c);
++	      continue;
++	    }
++
++	  if (c < 0xc0)
++	    break;
++
++	  /* We *might* have a UTF-8 sequence.  Time to start peeking.  */
++	  unsigned char utf8[4];
++
++	  utf8[0] = c;
++	  c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++	  if (c == EOF)
++	    break;
++	  utf8[1] = c;
++
++	  if ((utf8[1] & 0xc0) != 0x80)
++	    {
++	      /* Invalid UTF-8.  */
++	      putback_buf[num_putback++] = utf8[1];
++	      break;
++	    }
++	  else if ((utf8[0] & 0x20) == 0)
++	    {
++	      /* Valid 2-byte UTF-8.  */
++	      if (unicode_display == unicode_invalid)
++		{
++		  putback_buf[num_putback++] = utf8[1];
++		  break;
++		}
++	      else
++		{
++		  (void) display_utf8_char (utf8);
++		  continue;
++		}
++	    }
++
++	  c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++	  if (c == EOF)
++	    break;
++	  utf8[2] = c;
++
++	  if ((utf8[2] & 0xc0) != 0x80)
++	    {
++	      /* Invalid UTF-8.  */
++	      putback_buf[num_putback++] = utf8[2];
++	      putback_buf[num_putback++] = utf8[1];
++	      break;
++	    }
++	  else if ((utf8[0] & 0x10) == 0)
++	    {
++	      /* Valid 3-byte UTF-8.  */
++	      if (unicode_display == unicode_invalid)
++		{
++		  putback_buf[num_putback++] = utf8[2];
++		  putback_buf[num_putback++] = utf8[1];
++		  break;
++		}
++	      else
++		{
++		  (void) display_utf8_char (utf8);
++		  continue;
++		}
++	    }
++
++	  c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
++	  if (c == EOF)
++	    break;
++	  utf8[3] = c;
++
++	  if ((utf8[3] & 0xc0) != 0x80)
++	    {
++	      /* Invalid UTF-8.  */
++	      putback_buf[num_putback++] = utf8[3];
++	      putback_buf[num_putback++] = utf8[2];
++	      putback_buf[num_putback++] = utf8[1];
++	      break;
++	    }
++	  else if (unicode_display == unicode_invalid)
++	    {
++	      putback_buf[num_putback++] = utf8[3];
++	      putback_buf[num_putback++] = utf8[2];
++	      putback_buf[num_putback++] = utf8[1];
++	      break;
++	    }
++	  else
++	    /* A valid 4-byte UTF-8 encoding.  */
++	    (void) display_utf8_char (utf8);
++	}
++      while (1);
++
++      if (output_separator)
++	fputs (output_separator, stdout);
++      else
++	putchar ('\n');
++    }
++
++  if (c != EOF)
++    /* FIXME: Using tail recursion here is lazy, but it works.  */
++    print_unicode_stream_body (filename, address + num_read, stream, putback_buf, num_putback, print_buf);
++}
++
++/* Display strings read in from STREAM.  Treat any UTF-8 encoded characters
++   encountered according to the setting of the unicode_display variable.
++   The stream is positioned at ADDRESS and is attached to FILENAME.  */
++
++static void
++print_unicode_stream (const char * filename,
++		      file_ptr     address,
++		      FILE *       stream)
++{
++  /* Paranoia checks...  */
++  if (filename == NULL
++      || stream == NULL
++      || unicode_display == unicode_default
++      || encoding != 'S'
++      || encoding_bytes != 1)
++    {
++      fprintf (stderr, "ICE: bad arguments to print_unicode_stream\n");
++      return;
++    }
++
++  /* Allocate space for string_min 4-byte utf-8 characters.  */
++  unsigned char * print_buf = xmalloc ((4 * string_min) + 1);
++  /* We should never have to put back more than 4 bytes.  */
++  unsigned char putback_buf[5];
++  unsigned int num_putback = 0;
++
++  print_unicode_stream_body (filename, address, stream, putback_buf, num_putback, print_buf);
++  free (print_buf);
++}
+ 
+ /* Find the strings in file FILENAME, read from STREAM.
+    Assume that STREAM is positioned so that the next byte read
+    is at address ADDRESS in the file.
+-   Stop reading at address STOP_POINT in the file, if nonzero.
+ 
+    If STREAM is NULL, do not read from it.
+    The caller can supply a buffer of characters
+@@ -516,20 +1184,29 @@ get_char (FILE *stream, file_ptr *addres
+ 
+ static void
+ print_strings (const char *filename, FILE *stream, file_ptr address,
+-	       int stop_point, int magiccount, char *magic)
++	       int stop_point, int magiccount, char *magic)
+ {
++  if (unicode_display != unicode_default)
++    {
++      if (magic != NULL)
++	print_unicode_buffer (filename, address,
++			      (const unsigned char *) magic, magiccount);
++
++      if (stream != NULL)
++	print_unicode_stream (filename, address, stream);
++      return;
++    }
++
+   char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
+ 
+   while (1)
+     {
+       file_ptr start;
+-      int i;
++      unsigned int i;
+       long c;
+ 
+       /* See if the next `string_min' chars are all graphic chars.  */
+     tryline:
+-      if (stop_point && address >= stop_point)
+-	break;
+       start = address;
+       for (i = 0; i < string_min; i++)
+ 	{
+@@ -659,6 +1336,8 @@ usage (FILE *stream, int status)
+   -T --target=<BFDNAME>     Specify the binary file format\n\
+   -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
+                             s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
++  --unicode={default|show|invalid|hex|escape|highlight}\n\
++  -U {d|s|i|x|e|h}          Specify how to treat UTF-8 encoded unicode characters\n\
+   -s --output-separator=<string> String used to separate strings in output.\n\
+   @<file>                   Read options from <file>\n\
+   -h --help                 Display this information\n\
+--- binutils.orig/binutils/readelf.c	2021-10-20 12:39:41.715008273 +0100
++++ binutils-2.30/binutils/readelf.c	2021-10-20 14:05:42.242326079 +0100
+@@ -287,6 +287,18 @@ typedef enum print_mode
+ }
+ print_mode;
+ 
++typedef enum unicode_display_type
++{
++  unicode_locale,
++  unicode_escape,
++  unicode_hex,
++  unicode_highlight,
++  unicode_invalid
++} unicode_display_type;
++
++static unicode_display_type unicode_display = unicode_locale;
++
++  
+ /* Versioned symbol info.  */
+ enum versioned_symbol_info
+ {
+@@ -538,11 +550,18 @@ print_symbol (signed int width, const ch
+       if (c == 0)
+ 	break;
+ 
+-      /* Do not print control characters directly as they can affect terminal
+-	 settings.  Such characters usually appear in the names generated
+-	 by the assembler for local labels.  */
+-      if (ISCNTRL (c))
++      if (ISPRINT (c))
++	{
++	  putchar (c);
++	  width_remaining --;
++	  num_printed ++;
++	}
++      else if (ISCNTRL (c))
+ 	{
++	  /* Do not print control characters directly as they can affect terminal
++	     settings.  Such characters usually appear in the names generated
++	     by the assembler for local labels.  */
++
+ 	  if (width_remaining < 2)
+ 	    break;
+ 
+@@ -550,11 +569,135 @@ print_symbol (signed int width, const ch
+ 	  width_remaining -= 2;
+ 	  num_printed += 2;
+ 	}
+-      else if (ISPRINT (c))
++      else if (c == 0x7f)
+ 	{
+-	  putchar (c);
+-	  width_remaining --;
+-	  num_printed ++;
++	  if (width_remaining < 5)
++	    break;
++	  printf ("<DEL>");
++	  width_remaining -= 5;
++	  num_printed += 5;
++	}
++      else if (unicode_display != unicode_locale)
++	{
++	  /* Display unicode characters as something else.  */
++	  unsigned char bytes[4];
++	  bfd_boolean   is_utf8;
++	  unsigned int  nbytes;
++
++	  bytes[0] = c;
++
++	  if (bytes[0] < 0xc0)
++	    {
++	      nbytes = 1;
++	      is_utf8 = FALSE;
++	    }
++	  else
++	    {
++	      bytes[1] = *symbol++;
++
++	      if ((bytes[1] & 0xc0) != 0x80)
++		{
++		  is_utf8 = FALSE;
++		  /* Do not consume this character.  It may only
++		     be the first byte in the sequence that was
++		     corrupt.  */
++		  --symbol;
++		  nbytes = 1;
++		}
++	      else if ((bytes[0] & 0x20) == 0)
++		{
++		  is_utf8 = TRUE;
++		  nbytes = 2;
++		}
++	      else
++		{
++		  bytes[2] = *symbol++;
++
++		  if ((bytes[2] & 0xc0) != 0x80)
++		    {
++		      is_utf8 = FALSE;
++		      symbol -= 2;
++		      nbytes = 1;
++		    }
++		  else if ((bytes[0] & 0x10) == 0)
++		    {
++		      is_utf8 = TRUE;
++		      nbytes = 3;
++		    }
++		  else
++		    {
++		      bytes[3] = *symbol++;
++
++		      nbytes = 4;
++
++		      if ((bytes[3] & 0xc0) != 0x80)
++			{
++			  is_utf8 = FALSE;
++			  symbol -= 3;
++			  nbytes = 1;
++			}
++		      else
++			is_utf8 = TRUE;
++		    }
++		}
++	    }
++
++	  if (unicode_display == unicode_invalid)
++	    is_utf8 = FALSE;
++
++	  if (unicode_display == unicode_hex || ! is_utf8)
++	    {
++	      unsigned int i;
++
++	      if (width_remaining < (nbytes * 2) + 2)
++		break;
++	  
++	      putchar (is_utf8 ? '<' : '{');
++	      for (i = 0; i < nbytes; i++)
++		printf ("%02x", bytes[i]);
++	      putchar (is_utf8 ? '>' : '}');
++	    }
++	  else
++	    {
++	      if (unicode_display == unicode_highlight && isatty (1))
++		printf ("\x1B[31;47m"); /* Red.  */
++	      
++	      switch (nbytes)
++		{
++		case 2:
++		  if (width_remaining < 6)
++		    break;
++		  printf ("\\u%02x%02x",
++			  (bytes[0] & 0x1c) >> 2, 
++			  ((bytes[0] & 0x03) << 6) | (bytes[1] & 0x3f));
++		  break;
++		case 3:
++		  if (width_remaining < 6)
++		    break;
++		  printf ("\\u%02x%02x",
++			  ((bytes[0] & 0x0f) << 4) | ((bytes[1] & 0x3c) >> 2),
++			  ((bytes[1] & 0x03) << 6) | (bytes[2] & 0x3f));
++		  break;
++		case 4:
++		  if (width_remaining < 8)
++		    break;
++		  printf ("\\u%02x%02x%02x",
++			  ((bytes[0] & 0x07) << 6) | ((bytes[1] & 0x3c) >> 2),
++			  ((bytes[1] & 0x03) << 6) | ((bytes[2] & 0x3c) >> 2),
++			  ((bytes[2] & 0x03) << 6) | (bytes[3] & 0x3f));
++		  
++		  break;
++		default:
++		  /* URG.  */
++		  break;
++		}
++
++	      if (unicode_display == unicode_highlight && isatty (1))
++		printf ("\033[0m"); /* Default colour.  */
++	    }
++	  
++	  if (bytes[nbytes - 1] == 0)
++	    break;
+ 	}
+       else
+ 	{
+@@ -4375,6 +4518,7 @@ static struct option options[] =
+   {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
+   {"dwarf-check",      no_argument, 0, OPTION_DWARF_CHECK},
+ 
++  {"unicode",          required_argument, 0, 'U'},
+   {"version",	       no_argument, 0, 'v'},
+   {"wide",	       no_argument, 0, 'W'},
+   {"help",	       no_argument, 0, 'H'},
+@@ -4432,6 +4576,11 @@ usage (FILE * stream)
+   fprintf (stream, _("\
+   -I --histogram         Display histogram of bucket list lengths\n\
+   -W --wide              Allow output width to exceed 80 characters\n\
++  -U --unicode=[locale|escape|hex|highlight|invalid]\n\
++                         Display unicode characters as determined by the current locale\n\
++                          (default), escape sequences, \"<hex sequences>\", highlighted\n\
++                          escape sequences, or treat them as invalid and display as\n\
++                          \"{hex sequences}\"\n\
+   @<file>                Read options from <file>\n\
+   -H --help              Display this information\n\
+   -v --version           Display the version number of readelf\n"));
+@@ -4525,7 +4674,7 @@ parse_args (Filedata * filedata, int arg
+     usage (stderr);
+ 
+   while ((c = getopt_long
+-	  (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
++	  (argc, argv, "ADHINR:SU:VWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
+     {
+       switch (c)
+ 	{
+@@ -4659,6 +4808,25 @@ parse_args (Filedata * filedata, int arg
+ 	  request_dump (filedata, DISASS_DUMP);
+ 	  break;
+ #endif
++	case 'U':
++	  if (optarg == NULL)
++	    error (_("Missing arg to -U/--unicode")); /* Can this happen ?  */
++	  else if (streq (optarg, "default") || streq (optarg, "d"))
++	    unicode_display = unicode_locale;
++	  else if (streq (optarg, "locale") || streq (optarg, "l"))
++	    unicode_display = unicode_locale;
++	  else if (streq (optarg, "escape") || streq (optarg, "e"))
++	    unicode_display = unicode_escape;
++	  else if (streq (optarg, "invalid") || streq (optarg, "i"))
++	    unicode_display = unicode_invalid;
++	  else if (streq (optarg, "hex") || streq (optarg, "x"))
++	    unicode_display = unicode_hex;
++	  else if (streq (optarg, "highlight") || streq (optarg, "h"))
++	    unicode_display = unicode_highlight;
++	  else
++	    error (_("unknown argument to -U/--unicode: %s"), optarg);
++	  break;
++
+ 	case 'v':
+ 	  print_version (program_name);
+ 	  break;
diff --git a/SPECS/binutils.spec b/SPECS/binutils.spec
index d571952..de1e0df 100644
--- a/SPECS/binutils.spec
+++ b/SPECS/binutils.spec
@@ -43,7 +43,7 @@
 Summary: A GNU collection of binary utilities
 Name: binutils%{?name_cross}%{?_with_debug:-debug}
 Version: 2.30
-Release: 108%{?dist}
+Release: 113%{?dist}
 License: GPLv3+
 URL: https://sourceware.org/binutils
 
@@ -591,6 +591,26 @@ Patch91: binutils-clearing-discarded-relocs.patch
 # Lifetime: Fixed in 2.37 (maybe)
 Patch92: binutils-gold-i386-gnu-property-notes.patch
 
+# Purpose: Fix problems with the binutils-plugin-as-needed.patch
+# Lifetime: Fixed in 2.37
+Patch93: binutils-plugin-as-needed-correct.patch
+
+# Purpose:  Add support for the arch14 extensions to the s390x architecture.
+# Lifetime: Fixed in 2.37
+Patch94: binutils-s390x-arch14.patch
+
+# Purpose: Add options to control the display of multibyte characters.  CVE 2021-42574
+# Lifetime: Fixed in 2.38 (maybe)
+Patch95: binutils.unicode.patch
+
+# Purpose: Make undefined unversioned dynamic symbols global rather than local.
+# Lifetime: Fixed in 2.37
+Patch96: binutils-undefined-unversioned-symbols.patch
+
+# Purpose: When searching for plugins, do not complain if incompatible ones are found.
+# Lifetime: Fixed in 2.35
+Patch97: binutils-plugin-error.patch
+
 #----------------------------------------------------------------------------
 
 Provides: bundled(libiberty)
@@ -820,6 +840,11 @@ using libelf instead of BFD.
 %patch90 -p1
 %patch91 -p1
 %patch92 -p1
+%patch93 -p1
+%patch94 -p1
+%patch95 -p1
+%patch96 -p1
+%patch97 -p1
 
 # We cannot run autotools as there is an exact requirement of autoconf-2.59.
 # FIXME - this is no longer true.  Maybe try reinstating autotool use ?
@@ -1269,6 +1294,21 @@ exit 0
 
 #----------------------------------------------------------------------------
 %changelog
+* Wed Jan 19 2022 Nick Clifton  <nickc@redhat.com> - 2.30-113
+- When searching for plugins, do not complain if incompatible ones are found.  (#2039117)
+
+* Thu Dec 09 2021 Nick Clifton  <nickc@redhat.com> - 2.30-112
+- Make undefined unversioned dynamic symbols global rather than local.  (#2005176)
+
+* Mon Oct 25 2021 Nick Clifton  <nickc@redhat.com> - 2.30-111
+- Add ability to control the display of unicode characters.  (#2009173)
+
+* Wed Sep 29 2021 Nick Clifton  <nickc@redhat.com> - 2.30-110
+- Add support for the arch14 extensions to the s390x architecture.  (#1984819)
+
+* Wed Sep 29 2021 Nick Clifton  <nickc@redhat.com> - 2.30-109
+- Fix problems introduced by the plugin-as-needed patch.  (#2005412)
+
 * Wed Jul 07 2021 Nick Clifton  <nickc@redhat.com> - 2.30-108
 - Fix thinko in previous delta.  (#1970961)