Sophie

Sophie

distrib > Mageia > 7 > i586 > by-pkgid > 0e1fb6d48c993633711e2942dec89407 > files > 5

binutils-2.32-14.mga7.src.rpm

From 263825a224bdbdebbef7e96876dc7b8a45cbdc5b Mon Sep 17 00:00:00 2001
From: Tamar Christina <tamar.christina@arm.com>
Date: Mon, 25 Mar 2019 12:08:53 +0000
Subject: [PATCH] AArch64: Fix disassembler bug with out-of-order sections

The AArch64 disassembler has an optimization that it uses to reduce the amount
it has to search for mapping symbols during disassembly.  This optimization
assumes that sections are listed in the section header in monotonic increasing
VMAs.  However this is not a requirement for the ELF specification.

Because of this when such "out of order" sections occur the disassembler would
pick the wrong mapping symbol to disassemble the section with.

This fixes it by explicitly passing along the stop offset for the current
disassembly glob and when this changes compared to the previous one we've seen
the optimization won't be performed.  In effect this restarts the search from
a well defined starting point.  Usually the symbol's address.

The existing stop_vma can't be used for this as it is allowed to be unset and
setting this unconditionally would change the semantics of this field.

binutils/ChangeLog:

	* objdump.c (disassemble_bytes): Pass stop_offset.
	* testsuite/binutils-all/aarch64/out-of-order.T: New test.
	* testsuite/binutils-all/aarch64/out-of-order.d: New test.
	* testsuite/binutils-all/aarch64/out-of-order.s: New test.

include/ChangeLog:

	* dis-asm.h (struct disassemble_info): Add stop_offset.

opcodes/ChangeLog:

	* aarch64-dis.c (last_stop_offset): New.
	(print_insn_aarch64): Use stop_offset.

(cherry picked from commit 53b2f36bf6aa939feab6f82f05d7dad52f82660d)
---
 binutils/ChangeLog                            |  57 ++++
 binutils/objdump.c                            |   1 +
 .../binutils-all/aarch64/in-order-all.d       |  38 +++
 .../testsuite/binutils-all/aarch64/in-order.d |  28 ++
 .../binutils-all/aarch64/out-of-order-all.d   |  38 +++
 .../binutils-all/aarch64/out-of-order.T       |  14 +
 .../binutils-all/aarch64/out-of-order.d       |  27 ++
 .../binutils-all/aarch64/out-of-order.s       |  28 ++
 .../testsuite/binutils-all/arm/in-order-all.d |  48 ++++
 .../testsuite/binutils-all/arm/in-order.d     |  28 ++
 .../testsuite/binutils-all/arm/objdump.exp    |  14 +
 .../binutils-all/arm/out-of-order-all.d       |  48 ++++
 .../testsuite/binutils-all/arm/out-of-order.T |  14 +
 .../testsuite/binutils-all/arm/out-of-order.d |  27 ++
 .../testsuite/binutils-all/arm/out-of-order.s |  29 ++
 include/ChangeLog                             |   7 +
 include/dis-asm.h                             |   6 +
 ld/ChangeLog                                  |   5 +
 .../ld-arm/jump-reloc-veneers-cond-long.d     |   2 +-
 ld/testsuite/ld-arm/jump-reloc-veneers-long.d |   5 +-
 opcodes/ChangeLog                             |  33 +++
 opcodes/aarch64-dis.c                         |  52 +++-
 opcodes/arm-dis.c                             | 249 +++++++-----------
 23 files changed, 640 insertions(+), 158 deletions(-)
 create mode 100644 binutils/testsuite/binutils-all/aarch64/in-order-all.d
 create mode 100644 binutils/testsuite/binutils-all/aarch64/in-order.d
 create mode 100644 binutils/testsuite/binutils-all/aarch64/out-of-order-all.d
 create mode 100644 binutils/testsuite/binutils-all/aarch64/out-of-order.T
 create mode 100644 binutils/testsuite/binutils-all/aarch64/out-of-order.d
 create mode 100644 binutils/testsuite/binutils-all/aarch64/out-of-order.s
 create mode 100644 binutils/testsuite/binutils-all/arm/in-order-all.d
 create mode 100644 binutils/testsuite/binutils-all/arm/in-order.d
 create mode 100644 binutils/testsuite/binutils-all/arm/out-of-order-all.d
 create mode 100644 binutils/testsuite/binutils-all/arm/out-of-order.T
 create mode 100644 binutils/testsuite/binutils-all/arm/out-of-order.d
 create mode 100644 binutils/testsuite/binutils-all/arm/out-of-order.s

#diff --git a/binutils/ChangeLog b/binutils/ChangeLog
#index f837c37806..3b80f0dca7 100644
#--- a/binutils/ChangeLog
#+++ b/binutils/ChangeLog
#@@ -1,3 +1,60 @@
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-26  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* testsuite/binutils-all/aarch64/in-order-all.d: Update.
#+	* testsuite/binutils-all/aarch64/in-order.d: Likewise.
#+	* testsuite/binutils-all/aarch64/out-of-order-all.d: Likewise.
#+	* testsuite/binutils-all/aarch64/out-of-order.d: Likewise.
#+	* testsuite/binutils-all/aarch64/out-of-order.s: Likewise.
#+	* testsuite/binutils-all/arm/in-order-all.d: Likewise.
#+	* testsuite/binutils-all/arm/in-order.d: Likewise.
#+	* testsuite/binutils-all/arm/out-of-order-all.d: Likewise.
#+	* testsuite/binutils-all/arm/out-of-order.d: Likewise.
#+	* testsuite/binutils-all/arm/out-of-order.s: Likewise.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* testsuite/binutils-all/arm/in-order-all.d: New test.
#+	* testsuite/binutils-all/arm/in-order.d: New test.
#+	* testsuite/binutils-all/arm/objdump.exp: Support .d tests.
#+	* testsuite/binutils-all/arm/out-of-order-all.d: New test.
#+	* testsuite/binutils-all/arm/out-of-order.T: New test.
#+	* testsuite/binutils-all/arm/out-of-order.d: New test.
#+	* testsuite/binutils-all/arm/out-of-order.s: New test.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* testsuite/binutils-all/aarch64/in-order-all.d: New test.
#+	* testsuite/binutils-all/aarch64/out-of-order-all.d: New test.
#+	* testsuite/binutils-all/aarch64/out-of-order.d: Update.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* testsuite/binutils-all/aarch64/in-order.d: New test.
#+	* testsuite/binutils-all/aarch64/out-of-order.d: Disassemble data as
#+	well.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* objdump.c (disassemble_bytes): Pass stop_offset.
#+	* testsuite/binutils-all/aarch64/out-of-order.T: New test.
#+	* testsuite/binutils-all/aarch64/out-of-order.d: New test.
#+	* testsuite/binutils-all/aarch64/out-of-order.s: New test.
#+
# 2019-02-02  Nick Clifton  <nickc@redhat.com>
# 
# 	* configure: Regenerate.
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 872539068c..4b98e7b690 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -1971,6 +1971,7 @@ disassemble_bytes (struct disassemble_info * inf,
 		   disassembling code of course, and when -D is in effect.  */
 		inf->stop_vma = section->vma + stop_offset;
 
+	      inf->stop_offset = stop_offset;
 	      octets = (*disassemble_fn) (section->vma + addr_offset, inf);
 
 	      inf->stop_vma = 0;
diff --git a/binutils/testsuite/binutils-all/aarch64/in-order-all.d b/binutils/testsuite/binutils-all/aarch64/in-order-all.d
new file mode 100644
index 0000000000..a484ca7d17
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/in-order-all.d
@@ -0,0 +1,38 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -e v1 -Ttext-segment=0x400000
+#objdump: -D
+#name: Check if disassembler can handle all sections in default order
+
+.*: +file format .*aarch64.*
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	8b010000 	add	x0, x0, x1
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
+
+Disassembly of section \.rodata:
+
+.+ <\.rodata>:
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
+
+Disassembly of section .global:
+
+.+ <.+>:
+	...
diff --git a/binutils/testsuite/binutils-all/aarch64/in-order.d b/binutils/testsuite/binutils-all/aarch64/in-order.d
new file mode 100644
index 0000000000..1c0532e127
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/in-order.d
@@ -0,0 +1,28 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -e v1 -Ttext-segment=0x400000
+#objdump: -d
+#name: Check if disassembler can handle sections in default order
+
+.*: +file format .*aarch64.*
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.word	0x00000000
+
+Disassembly of section .func2:
+
+.+ <\.func2>:
+[^:]+:	8b010000 	add	x0, x0, x1
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.word	0x00000000
diff --git a/binutils/testsuite/binutils-all/aarch64/out-of-order-all.d b/binutils/testsuite/binutils-all/aarch64/out-of-order-all.d
new file mode 100644
index 0000000000..d3aa79e482
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/out-of-order-all.d
@@ -0,0 +1,38 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -T out-of-order.T
+#objdump: -D
+#name: Check if disassembler can handle all sections in different order than header
+
+.*: +file format .*aarch64.*
+
+Disassembly of section \.global:
+
+.+ <\.global>:
+	...
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	8b010000 	add	x0, x0, x1
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
+
+Disassembly of section \.rodata:
+
+.+ <\.rodata>:
+[^:]+:	00000000 	\.inst	0x00000000 ; undefined
diff --git a/binutils/testsuite/binutils-all/aarch64/out-of-order.T b/binutils/testsuite/binutils-all/aarch64/out-of-order.T
new file mode 100644
index 0000000000..489ae80190
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/out-of-order.T
@@ -0,0 +1,14 @@
+ENTRY(v1)
+SECTIONS
+{
+  . = 0xffe00000;
+  .global : { *(.global) }
+  . = 0x4018280;
+  .func2 : { *(.func2) }
+  . = 0x4005000;
+  .func1 : { *(.func1) }
+  . = 0x4015000;
+  .func3 : { *(.func3) }
+  .data : { *(.data) }
+  .rodata : { *(.rodata) }
+}
\ No newline at end of file
diff --git a/binutils/testsuite/binutils-all/aarch64/out-of-order.d b/binutils/testsuite/binutils-all/aarch64/out-of-order.d
new file mode 100644
index 0000000000..a807b71fa3
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/out-of-order.d
@@ -0,0 +1,27 @@
+#PROG: objcopy
+#ld: -T out-of-order.T
+#objdump: -d
+#name: Check if disassembler can handle sections in different order than header
+
+.*: +file format .*aarch64.*
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	8b010000 	add	x0, x0, x1
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.word	0x00000000
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	8b010000 	add	x0, x0, x1
+[^:]+:	00000000 	\.word	0x00000000
diff --git a/binutils/testsuite/binutils-all/aarch64/out-of-order.s b/binutils/testsuite/binutils-all/aarch64/out-of-order.s
new file mode 100644
index 0000000000..51e66d7d1c
--- /dev/null
+++ b/binutils/testsuite/binutils-all/aarch64/out-of-order.s
@@ -0,0 +1,28 @@
+	.text
+	.global v1
+	.section .func1,"ax",@progbits
+	.type v1 %function
+	.size v1, 4
+v1:
+	add x0, x0, x1
+	.word 0
+
+	.section .func2,"ax",@progbits
+	add x0, x0, x1
+
+	.section .func3,"ax",@progbits
+	add x0, x0, x1
+	add x0, x0, x1
+	add x0, x0, x1
+	add x0, x0, x1
+	add x0, x0, x1
+	.word 0
+
+	.data
+	.section .global,"aw",@progbits
+	.xword 0
+	.xword 0
+	.xword 0
+
+	.section .rodata
+	.word 0
diff --git a/binutils/testsuite/binutils-all/arm/in-order-all.d b/binutils/testsuite/binutils-all/arm/in-order-all.d
new file mode 100644
index 0000000000..5e51ca187a
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/in-order-all.d
@@ -0,0 +1,48 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -e v1 -Ttext-segment=0x400000
+#objdump: -D
+#name: Check if disassembler can handle all sections in default order
+
+.*: +file format .*arm.*
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	e0800001 	add	r0, r0, r1
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.rodata:
+
+.+ <\.rodata>:
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.global:
+
+.+ <.+>:
+	...
+
+Disassembly of section \.ARM\.attributes:
+
+.+ <\.ARM\.attributes>:
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+
diff --git a/binutils/testsuite/binutils-all/arm/in-order.d b/binutils/testsuite/binutils-all/arm/in-order.d
new file mode 100644
index 0000000000..a2c9b9ed9b
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/in-order.d
@@ -0,0 +1,28 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -e v1 -Ttext-segment=0x400000
+#objdump: -d
+#name: Check if disassembler can handle sections in default order
+
+.*: +file format .*arm.*
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	\.word	0x00000000
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	e0800001 	add	r0, r0, r1
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	\.word	0x00000000
diff --git a/binutils/testsuite/binutils-all/arm/objdump.exp b/binutils/testsuite/binutils-all/arm/objdump.exp
index 5013b18bd6..33e3fd1437 100644
--- a/binutils/testsuite/binutils-all/arm/objdump.exp
+++ b/binutils/testsuite/binutils-all/arm/objdump.exp
@@ -111,3 +111,17 @@ if {![binutils_assemble $srcdir/$subdir/rvct_symbol.s tmpdir/rvct_symbol.o]} the
 	fail "skip rvct symbol"
     }
 }
+
+###########################
+# Set up generic test framework
+###########################
+
+set tempfile tmpdir/armtemp.o
+set copyfile tmpdir/armcopy
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+foreach t $test_list {
+    # We need to strip the ".d", but can leave the dirname.
+    verbose [file rootname $t]
+    run_dump_test [file rootname $t]
+}
diff --git a/binutils/testsuite/binutils-all/arm/out-of-order-all.d b/binutils/testsuite/binutils-all/arm/out-of-order-all.d
new file mode 100644
index 0000000000..c1df003455
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/out-of-order-all.d
@@ -0,0 +1,48 @@
+#PROG: objcopy
+#source: out-of-order.s
+#ld: -T out-of-order.T
+#objdump: -D
+#name: Check if disassembler can handle all sections in different order than header
+
+.*: +file format .*arm.*
+
+Disassembly of section \.global:
+
+.+ <\.global>:
+	...
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	e0800001 	add	r0, r0, r1
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.rodata:
+
+.+ <\.rodata>:
+[^:]+:	00000000 	andeq	r0, r0, r0
+
+Disassembly of section \.ARM\.attributes:
+
+.+ <\.ARM\.attributes>:
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+[^:]+:	.+
+
diff --git a/binutils/testsuite/binutils-all/arm/out-of-order.T b/binutils/testsuite/binutils-all/arm/out-of-order.T
new file mode 100644
index 0000000000..489ae80190
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/out-of-order.T
@@ -0,0 +1,14 @@
+ENTRY(v1)
+SECTIONS
+{
+  . = 0xffe00000;
+  .global : { *(.global) }
+  . = 0x4018280;
+  .func2 : { *(.func2) }
+  . = 0x4005000;
+  .func1 : { *(.func1) }
+  . = 0x4015000;
+  .func3 : { *(.func3) }
+  .data : { *(.data) }
+  .rodata : { *(.rodata) }
+}
\ No newline at end of file
diff --git a/binutils/testsuite/binutils-all/arm/out-of-order.d b/binutils/testsuite/binutils-all/arm/out-of-order.d
new file mode 100644
index 0000000000..f880cbcb91
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/out-of-order.d
@@ -0,0 +1,27 @@
+#PROG: objcopy
+#ld: -T out-of-order.T
+#objdump: -d
+#name: Check if disassembler can handle sections in different order than header
+
+.*: +file format .*arm.*
+
+Disassembly of section \.func2:
+
+.+ <\.func2>:
+[^:]+:	e0800001 	add	r0, r0, r1
+
+Disassembly of section \.func1:
+
+.+ <v1>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	\.word	0x00000000
+
+Disassembly of section \.func3:
+
+.+ <\.func3>:
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	e0800001 	add	r0, r0, r1
+[^:]+:	00000000 	\.word	0x00000000
diff --git a/binutils/testsuite/binutils-all/arm/out-of-order.s b/binutils/testsuite/binutils-all/arm/out-of-order.s
new file mode 100644
index 0000000000..3994fe5249
--- /dev/null
+++ b/binutils/testsuite/binutils-all/arm/out-of-order.s
@@ -0,0 +1,29 @@
+	.text
+	.arm
+	.global v1
+	.section .func1,"ax",%progbits
+	.type v1 %function
+	.size v1, 4
+v1:
+	add r0, r0, r1
+	.word 0
+
+	.section .func2,"ax",%progbits
+	add r0, r0, r1
+
+	.section .func3,"ax",%progbits
+	add r0, r0, r1
+	add r0, r0, r1
+	add r0, r0, r1
+	add r0, r0, r1
+	add r0, r0, r1
+	.word 0
+
+	.data
+	.section .global,"aw",%progbits
+	.word 0
+	.word 0
+	.word 0
+
+	.section .rodata
+	.word 0
#diff --git a/include/ChangeLog b/include/ChangeLog
#index a5ca6d048e..899ef299ef 100644
#--- a/include/ChangeLog
#+++ b/include/ChangeLog
#@@ -1,3 +1,10 @@
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* dis-asm.h (struct disassemble_info): Add stop_offset.
#+
# 2019-02-02  Nick Clifton  <nickc@redhat.com>
# 
# 	2.32 Release.
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 22c593ece6..4e1263c90e 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -221,6 +221,12 @@ typedef struct disassemble_info
      file being disassembled.  */
   bfd_vma stop_vma;
 
+  /* The end range of the current range being disassembled.  This is required
+     in order to notify the disassembler when it's currently handling a
+     different range than it was before.  This prevent unsafe optimizations when
+     disassembling such as the way mapping symbols are found on AArch64.  */
+  bfd_vma stop_offset;
+
 } disassemble_info;
 
 /* This struct is used to pass information about valid disassembler
#diff --git a/ld/ChangeLog b/ld/ChangeLog
#index d719425ee6..192599f71d 100644
#--- a/ld/ChangeLog
#+++ b/ld/ChangeLog
#@@ -1,3 +1,8 @@
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* testsuite/ld-arm/jump-reloc-veneers-cond-long.d: Update disassembly.
#+	* testsuite/ld-arm/jump-reloc-veneers-long.d: Update disassembly.
#+
# 2019-02-09  Vineet Gupta  <vgupta@synopsys.com>
# 
# 	* emultempl/arclinux.em: Delete special INIT/FINI handling.
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d
index d818cf579e..88481f0e92 100644
--- a/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-cond-long.d
@@ -10,7 +10,7 @@ Disassembly of section destsect:
 Disassembly of section .text:
 
 000080.. <[^>]*>:
-    80..:	(8002f040|f0408002) 	.word	0x(8002f040|f0408002)
+    80..:	f040 8002 	bne.w	8008 <__dest_veneer>
     80..:	0000      	movs	r0, r0
 	...
 
diff --git a/ld/testsuite/ld-arm/jump-reloc-veneers-long.d b/ld/testsuite/ld-arm/jump-reloc-veneers-long.d
index 6bd5652de3..ae176bed8a 100644
--- a/ld/testsuite/ld-arm/jump-reloc-veneers-long.d
+++ b/ld/testsuite/ld-arm/jump-reloc-veneers-long.d
@@ -10,8 +10,9 @@ Disassembly of section destsect:
 Disassembly of section .text:
 
 000080.. <[^>]*>:
-    80..:	(b802f000|f000b802) 	.word	0x(b802f000|f000b802)
-    80..:	00000000 	andeq	r0, r0, r0
+    80..:	f000 b802 	b.w	8008 <__dest_veneer>
+    80..:	0000      	movs	r0, r0
+	...
 
 000080.. <[^>]*>:
     80..:	4778      	bx	pc
#diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
#index 9a3d094ef9..1a60acc383 100644
#--- a/opcodes/ChangeLog
#+++ b/opcodes/ChangeLog
#@@ -1,3 +1,36 @@
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* arm-dis.c (struct arm_private_data): Remove has_mapping_symbols.
#+	(mapping_symbol_for_insn): Implement new algorithm.
#+	(print_insn): Remove duplicate code.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* aarch64-dis.c (print_insn_aarch64):
#+	Implement override.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* aarch64-dis.c (print_insn_aarch64): Update the mapping symbol search
#+	order.
#+
#+2019-04-01  Tamar Christina  <tamar.christina@arm.com>
#+
#+	Backport from mainline.
#+	2019-03-25  Tamar Christina  <tamar.christina@arm.com>
#+
#+	* aarch64-dis.c (last_stop_offset): New.
#+	(print_insn_aarch64): Use stop_offset.
#+
# 2019-03-12  Andreas Krebbel  <krebbel@linux.ibm.com>
# 
# 	Backport from mainline
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 4c31f57451..eea649fd3c 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -37,6 +37,7 @@ enum map_type
 
 static enum map_type last_type;
 static int last_mapping_sym = -1;
+static bfd_vma last_stop_offset = 0;
 static bfd_vma last_mapping_addr = 0;
 
 /* Other options */
@@ -3317,14 +3318,26 @@ print_insn_aarch64 (bfd_vma pc,
   /* Aarch64 instructions are always little-endian */
   info->endian_code = BFD_ENDIAN_LITTLE;
 
+  /* Default to DATA.  A text section is required by the ABI to contain an
+     INSN mapping symbol at the start.  A data section has no such
+     requirement, hence if no mapping symbol is found the section must
+     contain only data.  This however isn't very useful if the user has
+     fully stripped the binaries.  If this is the case use the section
+     attributes to determine the default.  If we have no section default to
+     INSN as well, as we may be disassembling some raw bytes on a baremetal
+     HEX file or similar.  */
+  enum map_type type = MAP_DATA;
+  if ((info->section && info->section->flags & SEC_CODE) || !info->section)
+    type = MAP_INSN;
+
   /* First check the full symtab for a mapping symbol, even if there
      are no usable non-mapping symbols for this address.  */
   if (info->symtab_size != 0
       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
     {
-      enum map_type type = MAP_INSN;
       int last_sym = -1;
-      bfd_vma addr;
+      bfd_vma addr, section_vma = 0;
+      bfd_boolean can_use_search_opt_p;
       int n;
 
       if (pc <= last_mapping_addr)
@@ -3333,10 +3346,20 @@ print_insn_aarch64 (bfd_vma pc,
       /* Start scanning at the start of the function, or wherever
 	 we finished last time.  */
       n = info->symtab_pos + 1;
-      if (n < last_mapping_sym)
+
+      /* If the last stop offset is different from the current one it means we
+	 are disassembling a different glob of bytes.  As such the optimization
+	 would not be safe and we should start over.  */
+      can_use_search_opt_p = last_mapping_sym >= 0
+			     && info->stop_offset == last_stop_offset;
+
+      if (n >= last_mapping_sym && can_use_search_opt_p)
 	n = last_mapping_sym;
 
-      /* Scan up to the location being disassembled.  */
+      /* Look down while we haven't passed the location being disassembled.
+	 The reason for this is that there's no defined order between a symbol
+	 and an mapping symbol that may be at the same address.  We may have to
+	 look at least one position ahead.  */
       for (; n < info->symtab_size; n++)
 	{
 	  addr = bfd_asymbol_value (info->symtab[n]);
@@ -3352,13 +3375,24 @@ print_insn_aarch64 (bfd_vma pc,
       if (!found)
 	{
 	  n = info->symtab_pos;
-	  if (n < last_mapping_sym)
+	  if (n >= last_mapping_sym && can_use_search_opt_p)
 	    n = last_mapping_sym;
 
 	  /* No mapping symbol found at this address.  Look backwards
-	     for a preceeding one.  */
+	     for a preceeding one, but don't go pass the section start
+	     otherwise a data section with no mapping symbol can pick up
+	     a text mapping symbol of a preceeding section.  The documentation
+	     says section can be NULL, in which case we will seek up all the
+	     way to the top.  */
+	  if (info->section)
+	    section_vma = info->section->vma;
+
 	  for (; n >= 0; n--)
 	    {
+	      addr = bfd_asymbol_value (info->symtab[n]);
+	      if (addr < section_vma)
+		break;
+
 	      if (get_sym_code_type (info, n, &type))
 		{
 		  last_sym = n;
@@ -3370,6 +3404,7 @@ print_insn_aarch64 (bfd_vma pc,
 
       last_mapping_sym = last_sym;
       last_type = type;
+      last_stop_offset = info->stop_offset;
 
       /* Look a little bit ahead to see if we should print out
 	 less than four bytes of data.  If there's a symbol,
@@ -3395,8 +3430,11 @@ print_insn_aarch64 (bfd_vma pc,
 	    size = (pc & 1) ? 1 : 2;
 	}
     }
+  else
+    last_type = type;
 
-  if (last_type == MAP_DATA)
+  /* PR 10263: Disassemble data if requested to do so by the user.  */
+  if (last_type == MAP_DATA && ((info->flags & DISASSEMBLE_DATA) == 0))
     {
       /* size was set above.  */
       info->bytes_per_chunk = size;
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index 71d7c524a2..d47ef32b97 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -56,15 +56,14 @@ struct arm_private_data
   /* The features to use when disassembling optional instructions.  */
   arm_feature_set features;
 
-  /* Whether any mapping symbols are present in the provided symbol
-     table.  -1 if we do not know yet, otherwise 0 or 1.  */
-  int has_mapping_symbols;
-
   /* Track the last type (although this doesn't seem to be useful) */
   enum map_type last_type;
 
   /* Tracking symbol table information */
   int last_mapping_sym;
+
+  /* The end range of the current range being disassembled.  */
+  bfd_vma last_stop_offset;
   bfd_vma last_mapping_addr;
 };
 
@@ -6351,52 +6350,114 @@ static bfd_boolean
 mapping_symbol_for_insn (bfd_vma pc, struct disassemble_info *info,
 			 enum map_type *map_symbol)
 {
-  bfd_vma addr;
-  int n, start = 0;
+  bfd_vma addr, section_vma = 0;
+  int n, last_sym = -1;
   bfd_boolean found = FALSE;
-  enum map_type type = MAP_ARM;
+  bfd_boolean can_use_search_opt_p = FALSE;
+
+  /* Default to DATA.  A text section is required by the ABI to contain an
+     INSN mapping symbol at the start.  A data section has no such
+     requirement, hence if no mapping symbol is found the section must
+     contain only data.  This however isn't very useful if the user has
+     fully stripped the binaries.  If this is the case use the section
+     attributes to determine the default.  If we have no section default to
+     INSN as well, as we may be disassembling some raw bytes on a baremetal
+     HEX file or similar.  */
+  enum map_type type = MAP_DATA;
+  if ((info->section && info->section->flags & SEC_CODE) || !info->section)
+    type = MAP_ARM;
   struct arm_private_data *private_data;
 
-  if (info->private_data == NULL || info->symtab_size == 0
+  if (info->private_data == NULL
       || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour)
     return FALSE;
 
   private_data = info->private_data;
-  if (pc == 0)
-    start = 0;
-  else
-    start = private_data->last_mapping_sym;
 
-  start = (start == -1)? 0 : start;
-  addr = bfd_asymbol_value (info->symtab[start]);
+  /* First, look for mapping symbols.  */
+  if (info->symtab_size != 0)
+  {
+    if (pc <= private_data->last_mapping_addr)
+      private_data->last_mapping_sym = -1;
+
+    /* Start scanning at the start of the function, or wherever
+       we finished last time.  */
+    n = info->symtab_pos + 1;
+
+    /* If the last stop offset is different from the current one it means we
+       are disassembling a different glob of bytes.  As such the optimization
+       would not be safe and we should start over.  */
+    can_use_search_opt_p
+      = private_data->last_mapping_sym >= 0
+	&& info->stop_offset == private_data->last_stop_offset;
+
+    if (n >= private_data->last_mapping_sym && can_use_search_opt_p)
+      n = private_data->last_mapping_sym;
+
+    /* Look down while we haven't passed the location being disassembled.
+       The reason for this is that there's no defined order between a symbol
+       and an mapping symbol that may be at the same address.  We may have to
+       look at least one position ahead.  */
+    for (; n < info->symtab_size; n++)
+      {
+	addr = bfd_asymbol_value (info->symtab[n]);
+	if (addr > pc)
+	  break;
+	if (get_map_sym_type (info, n, &type))
+	  {
+	    last_sym = n;
+	    found = TRUE;
+	  }
+      }
 
-  if (pc >= addr)
-    {
-      if (get_map_sym_type (info, start, &type))
-      found = TRUE;
-    }
-  else
+    if (!found)
+      {
+	n = info->symtab_pos;
+	if (n >= private_data->last_mapping_sym && can_use_search_opt_p)
+	  n = private_data->last_mapping_sym;
+
+	/* No mapping symbol found at this address.  Look backwards
+	   for a preceeding one, but don't go pass the section start
+	   otherwise a data section with no mapping symbol can pick up
+	   a text mapping symbol of a preceeding section.  The documentation
+	   says section can be NULL, in which case we will seek up all the
+	   way to the top.  */
+	if (info->section)
+	  section_vma = info->section->vma;
+
+	for (; n >= 0; n--)
+	  {
+	    addr = bfd_asymbol_value (info->symtab[n]);
+	    if (addr < section_vma)
+	      break;
+
+	    if (get_map_sym_type (info, n, &type))
+	      {
+		last_sym = n;
+		found = TRUE;
+		break;
+	      }
+	  }
+      }
+  }
+
+  /* If no mapping symbol was found, try looking up without a mapping
+     symbol.  This is done by walking up from the current PC to the nearest
+     symbol.  We don't actually have to loop here since symtab_pos will
+     contain the nearest symbol already.  */
+  if (!found)
     {
-      for (n = start - 1; n >= 0; n--)
+      n = info->symtab_pos;
+      if (n >= 0 && get_sym_code_type (info, n, &type))
 	{
-	  if (get_map_sym_type (info, n, &type))
-	    {
-	      found = TRUE;
-	      break;
-	    }
+	  last_sym = n;
+	  found = TRUE;
 	}
     }
 
-  /* No mapping symbols were found.  A leading $d may be
-     omitted for sections which start with data; but for
-     compatibility with legacy and stripped binaries, only
-     assume the leading $d if there is at least one mapping
-     symbol in the file.  */
-  if (!found && private_data->has_mapping_symbols == 1)
-    {
-      type = MAP_DATA;
-      found = TRUE;
-    }
+  private_data->last_mapping_sym = last_sym;
+  private_data->last_type = type;
+  private_data->last_stop_offset = info->stop_offset;
 
   *map_symbol = type;
   return found;
@@ -6535,9 +6596,9 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
 	 during disassembly....  */
       select_arm_features (info->mach, & private.features);
 
-      private.has_mapping_symbols = -1;
       private.last_mapping_sym = -1;
       private.last_mapping_addr = 0;
+      private.last_stop_offset = 0;
 
       info->private_data = & private;
     }
@@ -6554,121 +6615,13 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
     {
       bfd_vma addr;
-      int n, start;
+      int n;
       int last_sym = -1;
       enum map_type type = MAP_ARM;
 
-      /* Start scanning at the start of the function, or wherever
-	 we finished last time.  */
-      /* PR 14006.  When the address is 0 we are either at the start of the
-	 very first function, or else the first function in a new, unlinked
-	 executable section (eg because of -ffunction-sections).  Either way
-	 start scanning from the beginning of the symbol table, not where we
-	 left off last time.  */
-      if (pc == 0)
-	start = 0;
-      else
-	{
-	  start = info->symtab_pos + 1;
-	  if (start < private_data->last_mapping_sym)
-	    start = private_data->last_mapping_sym;
-	}
-      found = FALSE;
-
-      /* First, look for mapping symbols.  */
-      if (private_data->has_mapping_symbols != 0)
-	{
-	  /* Scan up to the location being disassembled.  */
-	  for (n = start; n < info->symtab_size; n++)
-	    {
-	      addr = bfd_asymbol_value (info->symtab[n]);
-	      if (addr > pc)
-		break;
-	      if (get_map_sym_type (info, n, &type))
-		{
-		  last_sym = n;
-		  found = TRUE;
-		}
-	    }
-
-	  if (!found)
-	    {
-	      /* No mapping symbol found at this address.  Look backwards
-		 for a preceding one.  */
-	      for (n = start - 1; n >= 0; n--)
-		{
-		  if (get_map_sym_type (info, n, &type))
-		    {
-		      last_sym = n;
-		      found = TRUE;
-		      break;
-		    }
-		}
-	    }
-
-	  if (found)
-	    private_data->has_mapping_symbols = 1;
-
-	  /* No mapping symbols were found.  A leading $d may be
-	     omitted for sections which start with data; but for
-	     compatibility with legacy and stripped binaries, only
-	     assume the leading $d if there is at least one mapping
-	     symbol in the file.  */
-	  if (!found && private_data->has_mapping_symbols == -1)
-	    {
-	      /* Look for mapping symbols, in any section.  */
-	      for (n = 0; n < info->symtab_size; n++)
-		if (is_mapping_symbol (info, n, &type))
-		  {
-		    private_data->has_mapping_symbols = 1;
-		    break;
-		  }
-	      if (private_data->has_mapping_symbols == -1)
-		private_data->has_mapping_symbols = 0;
-	    }
-
-	  if (!found && private_data->has_mapping_symbols == 1)
-	    {
-	      type = MAP_DATA;
-	      found = TRUE;
-	    }
-	}
-
-      /* Next search for function symbols to separate ARM from Thumb
-	 in binaries without mapping symbols.  */
-      if (!found)
-	{
-	  /* Scan up to the location being disassembled.  */
-	  for (n = start; n < info->symtab_size; n++)
-	    {
-	      addr = bfd_asymbol_value (info->symtab[n]);
-	      if (addr > pc)
-		break;
-	      if (get_sym_code_type (info, n, &type))
-		{
-		  last_sym = n;
-		  found = TRUE;
-		}
-	    }
-
-	  if (!found)
-	    {
-	      /* No mapping symbol found at this address.  Look backwards
-		 for a preceding one.  */
-	      for (n = start - 1; n >= 0; n--)
-		{
-		  if (get_sym_code_type (info, n, &type))
-		    {
-		      last_sym = n;
-		      found = TRUE;
-		      break;
-		    }
-		}
-	    }
-	}
+      found = mapping_symbol_for_insn (pc, info, &type);
+      last_sym = private_data->last_mapping_sym;
 
-      private_data->last_mapping_sym = last_sym;
-      private_data->last_type = type;
       is_thumb = (private_data->last_type == MAP_THUMB);
       is_data = (private_data->last_type == MAP_DATA);
 
-- 
2.21.0