Skip to content

Commit 53b2f36

Browse files
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.
1 parent 9a93502 commit 53b2f36

File tree

9 files changed

+98
-1
lines changed

9 files changed

+98
-1
lines changed

binutils/ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2019-03-25 Tamar Christina <[email protected]>
2+
3+
* objdump.c (disassemble_bytes): Pass stop_offset.
4+
* testsuite/binutils-all/aarch64/out-of-order.T: New test.
5+
* testsuite/binutils-all/aarch64/out-of-order.d: New test.
6+
* testsuite/binutils-all/aarch64/out-of-order.s: New test.
7+
18
2019-03-19 Nick Clifton <[email protected]>
29

310
PR 24360

binutils/objdump.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,6 +1991,7 @@ disassemble_bytes (struct disassemble_info * inf,
19911991
disassembling code of course, and when -D is in effect. */
19921992
inf->stop_vma = section->vma + stop_offset;
19931993

1994+
inf->stop_offset = stop_offset;
19941995
octets = (*disassemble_fn) (section->vma + addr_offset, inf);
19951996

19961997
inf->stop_vma = 0;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ENTRY(v1)
2+
SECTIONS
3+
{
4+
. = 0xffe00000;
5+
.global : { *(.global) }
6+
. = 0x4018280;
7+
.func2 : { *(.func2) }
8+
. = 0x4005000;
9+
.func1 : { *(.func1) }
10+
. = 0x4015000;
11+
.func3 : { *(.func3) }
12+
.data : { *(.data) }
13+
.rodata : { *(.rodata) }
14+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#PROG: objcopy
2+
#ld: -T out-of-order.T
3+
#objdump: -d
4+
#name: Check if disassembler can handle sections in different order than header
5+
6+
.*: +file format .*aarch64.*
7+
8+
Disassembly of section \.func2:
9+
10+
0000000004018280 <\.func2>:
11+
4018280: 8b010000 add x0, x0, x1
12+
13+
Disassembly of section \.func1:
14+
15+
0000000004005000 <v1>:
16+
4005000: 8b010000 add x0, x0, x1
17+
4005004: 00000000 \.word 0x00000000
18+
19+
Disassembly of section \.func3:
20+
21+
0000000004015000 <\.func3>:
22+
4015000: 8b010000 add x0, x0, x1
23+
4015004: 8b010000 add x0, x0, x1
24+
4015008: 8b010000 add x0, x0, x1
25+
401500c: 8b010000 add x0, x0, x1
26+
4015010: 8b010000 add x0, x0, x1
27+
4015014: 00000000 \.word 0x00000000
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.text
2+
.global v1
3+
.section .func1,"ax",@progbits
4+
.type v1 %function
5+
.size v1, 4
6+
v1:
7+
add x0, x0, x1
8+
.word 0
9+
10+
.section .func2,"ax",@progbits
11+
add x0, x0, x1
12+
13+
.section .func3,"ax",@progbits
14+
add x0, x0, x1
15+
add x0, x0, x1
16+
add x0, x0, x1
17+
add x0, x0, x1
18+
add x0, x0, x1
19+
.word 0
20+
21+
.data
22+
.section .global,"aw",@progbits
23+
.xword 1
24+
.xword 1
25+
.xword 1
26+
27+
.section .rodata
28+
.word 4

include/ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2019-03-25 Tamar Christina <[email protected]>
2+
3+
* dis-asm.h (struct disassemble_info): Add stop_offset.
4+
15
2019-03-13 Sudakshina Das <[email protected]>
26

37
* elf/aarch64.h (DT_AARCH64_PAC_PLT): New.

include/dis-asm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ typedef struct disassemble_info
221221
file being disassembled. */
222222
bfd_vma stop_vma;
223223

224+
/* The end range of the current range being disassembled. This is required
225+
in order to notify the disassembler when it's currently handling a
226+
different range than it was before. This prevent unsafe optimizations when
227+
disassembling such as the way mapping symbols are found on AArch64. */
228+
bfd_vma stop_offset;
229+
224230
} disassemble_info;
225231

226232
/* This struct is used to pass information about valid disassembler

opcodes/ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2019-03-25 Tamar Christina <[email protected]>
2+
3+
* aarch64-dis.c (last_stop_offset): New.
4+
(print_insn_aarch64): Use stop_offset.
5+
16
2019-03-19 H.J. Lu <[email protected]>
27

38
PR gas/24359

opcodes/aarch64-dis.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ enum map_type
3737

3838
static enum map_type last_type;
3939
static int last_mapping_sym = -1;
40+
static bfd_vma last_stop_offset = 0;
4041
static bfd_vma last_mapping_addr = 0;
4142

4243
/* Other options */
@@ -3333,7 +3334,10 @@ print_insn_aarch64 (bfd_vma pc,
33333334
/* Start scanning at the start of the function, or wherever
33343335
we finished last time. */
33353336
n = info->symtab_pos + 1;
3336-
if (n < last_mapping_sym)
3337+
/* If the last stop offset is different from the current one it means we
3338+
are disassembling a different glob of bytes. As such the optimization
3339+
would not be safe and we should start over. */
3340+
if (n < last_mapping_sym && info->stop_offset == last_stop_offset)
33373341
n = last_mapping_sym;
33383342

33393343
/* Scan up to the location being disassembled. */
@@ -3370,6 +3374,7 @@ print_insn_aarch64 (bfd_vma pc,
33703374

33713375
last_mapping_sym = last_sym;
33723376
last_type = type;
3377+
last_stop_offset = info->stop_offset;
33733378

33743379
/* Look a little bit ahead to see if we should print out
33753380
less than four bytes of data. If there's a symbol,

0 commit comments

Comments
 (0)