シンボル間の引き算
再配置情報について調べてたらアセンブリでのシンボル間の引き算についてelf/i386とmach-o/x86-64で挙動が違ったのでめも.
elf/i386 の場合
(実行環境: Ubuntu 10.04LTS (linux 2.6.32), GNU assembler version 2.20.1 (i486-linux-gnu))
まず.シンボル間の足し算はできません(当然)
.data a: .byte 1 b: .byte 2 z: .long b+a
$ gcc -c -o a.o a.s a.s: Assembler messages: a.s:9: Error: invalid sections for operation on `b' and `a'
以下の演算はできます
.data a: .byte 1 b: .byte 2 c: .byte 3 d: .byte 4 u: .long a # もちろんOK. R_386_32な再配置(aのアドレス) x: .long b - a # OK. この場合は再配置は必要ない y: .long c - b - a # OK. この場合は再配置が必要
$ gcc -c -o a.o a.s $ objdump -r a.o ... RELOCATION RECORDS FOR [.data]: OFFSET TYPE VALUE 00000004 R_386_32 .data 0000000c R_386_PC32 *ABS*
最後のyは.dataセクションがロードされるアドレスを引く必要があるため,再配置が必要となります.実際の再配置種別的にはR_386_PC32であるので,yにはaddendとしてc-b-a+yの値が入っています.
$ objdump -D a.o 00000000 <a>: 0: 01 02 add %eax,(%edx) 00000001 <b>: 1: 02 03 add (%ebx),%al 00000002 <c>: 2: 03 04 00 add (%eax,%eax,1),%eax ... 0000000c <y>: c: 0d .byte 0xd # y に入っている値は0x0d d: 00 00 add %al,(%eax) # これはc-b-a+y
異なるセクション間のシンボルの引き算はできません
.text a: .byte 1 .data b: .byte 2 z: .long b-a
$ gcc -c -o a.o a.s a.s: Assembler messages: a.s:10: Error: can't resolve `.data' {.data section} - `a' {.text section}
Mach-O/x86-64 の場合
(実行環境:Mac OS X 10.8,Apple Inc version cctools-836, GNU assembler version
1.38)
シンボルの足し算ができないのは同じです.
引き算は一つまで.
.data a: .quad 1 b: .quad 2 c: .quad 3 x: .quad a # もちろんOK. # X86_64_RELOC_UNSIGNED な再配置 y: .quad b - a # OK. mach-oでは再配置が必要 # (X86_64_RELOC_SUBTRACTORとX86_64_RELOC_UNSIGNED)
% gcc -c -o a.o a.s % otool -rv a.o z.o: Relocation information (__DATA,__data) 3 entries address pcrel length extern type scattered symbolnum/value 00000020 False quad True SUB False a 00000020 False quad True UNSIGND False b 00000018 False quad True UNSIGND False a
3つの引き算はできません.
.data a: .quad 1 b: .quad 2 c: .quad 3 z: .quad c - b - a # できない
% gcc -c -o z.o z.s z.s:8:Expression too complex, 2 symbols forgotten: "b" "a"
異なるセクション間のシンボルの引き算はできます(!)
.text a: .quad 1 .data b: .quad 1 z: .quad b-a
z: % gcc -c -o z.o z.s % otool -rv z.o Relocation information (__DATA,__data) 2 entries address pcrel length extern type scattered symbolnum/value 00000008 False quad True SUB False a 00000008 False quad True UNSIGND False b
まぁ,だから何,という話ですが..