[LLVMbugs] [Bug 18019] New: ARM integrated assembler generates incorrect nop opcode when switching from arm to thumb mode
bugzilla-daemon at llvm.org
bugzilla-daemon at llvm.org
Thu Nov 21 17:24:25 PST 2013
http://llvm.org/bugs/show_bug.cgi?id=18019
Bug ID: 18019
Summary: ARM integrated assembler generates incorrect nop
opcode when switching from arm to thumb mode
Product: tools
Version: trunk
Hardware: PC
OS: Windows NT
Status: NEW
Severity: normal
Priority: P
Component: llc
Assignee: unassignedbugs at nondot.org
Reporter: dpeixott at codeaurora.org
CC: llvmbugs at cs.uiuc.edu
Classification: Unclassified
I am seeing a problem with the way nops are emitted in the integrated assembler
for ARM. When switching from arm to thumb mode in an assembly file we still
emit the arm nop opcode. Look at this small example:
$ cat align.s
.syntax unified
.code 16
foo:
add r0, r0
.align 3
add r0, r0
$ llvm-mc -triple armv7-none-linux align.s -filetype=obj -o t.o && llvm-objdump
-triple thumbv7 -d t.o
t.o: file format ELF32-arm
Disassembly of section .text:
foo:
0: 00 44 add r0,
r0
2: 00 f0 20 e3 blx
#4195904
6: 00 00 movs r0,
r0
8: 00 44 add r0,
r0
This shows that we have actually emitted an arm nop (e320f000) instead of a
thumb nop. Unfortunately, this encodes to a thumb branch which causes bad
things to happen when compiling assembly code with align directives.
The ARMAsmBackend class is responsible for emitting these nops. It keeps track
of whether it should emit arm or thumb nop. The first problem is that
MCElfStreamer does not pass on the `.code 16` directive to the ARMAsmBackend
class (using handleAssemblerFlag). In the example above we start assembling in
arm mode (because of the -triple) and so the ARMAsmBackend always thinks we are
in arm mode and it emits the wrong opcode.
We actually can assemble this example correctly for darwin because the
MCMachOStreamer does pass on the directives. It looks like we need to modify
the MCElfStreamer to pass the assembler directives down to the ARMAsmBackend to
match the behavior of the MCMachOStreamer.
Unfortunately, this change will not solve the full problem, even though the
integrated assembler works correctly for MachO in this example:
$ llvm-mc -triple armv7-apple-darwin align.s -filetype=obj -o t.o &&
llvm-objdump -triple thumbv7 -d t.o
t.o: file format Mach-O arm
Disassembly of section __TEXT,__text:
foo:
0: 00 44 add r0,
r0
2: 00 bf nop
4: 00 bf nop
6: 00 bf nop
8: 00 44 add r0,
r0
The problem is that the nops are written after the assembly is complete when it
writes the MCAlignFragment to the output. The ARMAsmBackend writes nops using
the last mode it knew about. So it can write bad nop data if the nops are in a
location that is a mode that does not match the bit stored in the backend. We
can see the problem by simply adding a `.code 32` directive to the end of the
example:
$ echo ".code 32" >> align.s
$ llvm-mc -triple armv7-apple-darwin align.s -filetype=obj -o t.o &&
llvm-objdump -triple thumbv7 -d t.o
t.o: file format Mach-O arm
Disassembly of section __TEXT,__text:
foo:
0: 00 44 add r0,
r0
2: 00 f0 20 e3 blx
#4195904
6: 00 00 movs r0,
r0
8: 00 44 add r0,
r0
It seems that the MCAlignFragment needs to know if it is aligning in thumb mode
or in arm mode. How should we solve this problem? Should we store the current
mode in the fragment when assembling the file and use that mode when writing
nop data?
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20131122/8ead6c96/attachment.html>
More information about the llvm-bugs
mailing list