Incorrect assembly of NASM indirect addresses on macOS
Building the following code on macOS:
global start
default rel
section .text
start:
lea rdx, [buffer + 0]
lea rdx, [buffer + 1]
lea rdx, [buffer + 2]
lea rdx, [buffer + 3]
lea rdx, [buffer + 4]
lea rdx, [buffer + 5]
lea rdx, [buffer + 6]
lea rdx, [buffer + 7]
lea rdx, [buffer + 8]
section .data
buffer: db 0,0,0
using the command nasm -fmacho64 -w+all test.asm -o test.o
produces: (c gobjdump -d test.o
)
0000000000000000 <start>:
0: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 3f <buffer>
7: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 40 <buffer+0x1>
e: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 41 <buffer+0x2>
15: 48 8d 15 26 00 00 00 lea 0x26(%rip),%rdx # 42 <buffer+0x3>
1c: 48 8d 15 20 00 00 00 lea 0x20(%rip),%rdx # 43 <buffer+0x4>
23: 48 8d 15 1a 00 00 00 lea 0x1a(%rip),%rdx # 44 <buffer+0x5>
2a: 48 8d 15 14 00 00 00 lea 0x14(%rip),%rdx # 45 <buffer+0x6>
31: 48 8d 15 0e 00 00 00 lea 0xe(%rip),%rdx # 46 <buffer+0x7>
38: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 47 <buffer+0x8>
It looks right. Then, linking this to the executable with ld test.o -o test
, we get: (c gobjdump -d test
)
0000000000001fc1 <start>:
1fc1: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 2000 <buffer>
1fc8: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 2001 <buffer+0x1>
1fcf: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 2002 <buffer+0x2>
1fd6: 48 8d 15 23 00 00 00 lea 0x23(%rip),%rdx # 2000 <buffer>
1fdd: 48 8d 15 1d 00 00 00 lea 0x1d(%rip),%rdx # 2001 <buffer+0x1>
1fe4: 48 8d 15 17 00 00 00 lea 0x17(%rip),%rdx # 2002 <buffer+0x2>
1feb: 48 8d 15 11 00 00 00 lea 0x11(%rip),%rdx # 2003 <buffer+0x3>
1ff2: 48 8d 15 0b 00 00 00 lea 0xb(%rip),%rdx # 2004 <buffer+0x4>
1ff9: 48 8d 15 05 00 00 00 lea 0x5(%rip),%rdx # 2005 <buffer+0x5>
And all of a sudden, unexpectedly buffer + n is replaced with buffer + (n - 3) if n> = 3. The nasm version I'm using is 2.13.01 and ld is the macOS Sierra system linker, with ld -v
giving:
@(#)PROGRAM:ld PROJECT:ld64-274.2
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
LTO support using: LLVM version 8.0.0, (clang-800.0.42.1)
TAPI support using: Apple TAPI version 1.30
Why is this happening? Note that the same code seems to collect and bundle fine on linux and also uses yasm . I read elsewhere that nasm has some strange problems with the Mach-O 64 format, so this is probably a nasm bug in this area.
source to share
This seems to have been fixed in nasm version 2.13.03 as tested today. (Also in 2.13.02, but this version has other problems with macho64 target anyway, the output of re @MichaelPetch; .02 in this case is 0.0.) Output for test.asm and the commands given in the question.
nasm -fmacho64 -w+all test.asm -o test.o
; gobjdump -d test.o
:
test.o: file format mach-o-x86-64
Disassembly of section .text:
0000000000000000 <start>:
0: 48 8d 15 00 00 00 00 lea 0x0(%rip),%rdx # 7 <start+0x7>
7: 48 8d 15 01 00 00 00 lea 0x1(%rip),%rdx # f <start+0xf>
e: 48 8d 15 02 00 00 00 lea 0x2(%rip),%rdx # 17 <start+0x17>
15: 48 8d 15 03 00 00 00 lea 0x3(%rip),%rdx # 1f <start+0x1f>
1c: 48 8d 15 04 00 00 00 lea 0x4(%rip),%rdx # 27 <start+0x27>
23: 48 8d 15 05 00 00 00 lea 0x5(%rip),%rdx # 2f <start+0x2f>
2a: 48 8d 15 06 00 00 00 lea 0x6(%rip),%rdx # 37 <start+0x37>
31: 48 8d 15 07 00 00 00 lea 0x7(%rip),%rdx # 3f <buffer>
38: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 47 <buffer+0x8>
ld test.o -o test
; gobjdump -d test
:
test: file format mach-o-x86-64
Disassembly of section .text:
0000000000001fc1 <start>:
1fc1: 48 8d 15 38 00 00 00 lea 0x38(%rip),%rdx # 2000 <buffer>
1fc8: 48 8d 15 32 00 00 00 lea 0x32(%rip),%rdx # 2001 <buffer+0x1>
1fcf: 48 8d 15 2c 00 00 00 lea 0x2c(%rip),%rdx # 2002 <buffer+0x2>
1fd6: 48 8d 15 26 00 00 00 lea 0x26(%rip),%rdx # 2003 <buffer+0x3>
1fdd: 48 8d 15 20 00 00 00 lea 0x20(%rip),%rdx # 2004 <buffer+0x4>
1fe4: 48 8d 15 1a 00 00 00 lea 0x1a(%rip),%rdx # 2005 <buffer+0x5>
1feb: 48 8d 15 14 00 00 00 lea 0x14(%rip),%rdx # 2006 <buffer+0x6>
1ff2: 48 8d 15 0e 00 00 00 lea 0xe(%rip),%rdx # 2007 <buffer+0x7>
1ff9: 48 8d 15 08 00 00 00 lea 0x8(%rip),%rdx # 2008 <buffer+0x8>
It's worth noting that mine has been ld
updated and ld -v
now gives:
@(#)PROGRAM:ld PROJECT:ld64-305
configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em (tvOS)
LTO support using: LLVM version 9.0.0, (clang-900.0.39.2) (static support for 21, runtime is 21)
TAPI support using: Apple TAPI version 900.0.15 (tapi-900.0.15)
source to share