Я пытаюсь создать программу сборки с синтаксисом GAS, которая может обращаться к ее переменным из секции .data
независимо от положения в арке x86-64 с применением 32bit arch и IS (%eip
вместо %rip
).
Независимо от того, какие регистры я пробовал, лучший результат, который я получил, был Segmentation fault: 11
, и даже это для доступа к EIP, который я не должен был делать вообще, поэтому SF. Лучший результат, потому что это, по крайней мере, сказало мне что-то иное, чем «я не подойду».
Я компилирую файл с gcc
в macOS 10.13.6 середина 2010 года Intel Core 2 Duo (поэтому clang
, вероятно):
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
и передачи компоновщику некоторых параметров с помощью:
gcc -m32 -Wl,-fatal_warnings,-arch_errors_fatal,-warn_commons,-pie test.s
ld: предупреждение: пирог отключен. Абсолютная адресация (возможно, -mdynamic-no-pic) не разрешена в коде, подписанном PIE, но используется в _main из /whwhat.../test-a07cf9.o. Чтобы исправить это предупреждение, не компилируйте с -mdynamic-no-pic и не связывайте с -Wl, -no_pie
ld: фатальное предупреждение (я) вызвало ошибку (-fatal_warnings)
clang: error: сбой команды компоновщика с кодом выхода 1 (используйте -v для просмотра вызова)
1
test.s
.text
.global _main
_main:
xor %eax, %eax
xor %ebx, %ebx
# lea var1(%esi/edi/ebp/esp), %ebx # can't compile, not PIE
# lea var1(%eip), %ebx # segfault, obvs
# lea (%esp), %ebx # EBX = 17
# lea (%non-esp), %ebx # segfault
# lea 0(%esi), %ebx # segfault
# lea 0(%edi), %ebx # segfault
# lea 0(%ebp), %ebx # EBX = 0
# lea 0(%esp), %ebx # EBX = 17
# lea 0(%eip), %ebx # segfault, obvs
movl (%ebx), %eax
ret
.data
var1: .long 6
.end
Я запускаю его с ./a.out; echo $?
, чтобы проверить значение EAX от ret
в конце.
Я посмотрел на различные источники, но в основном это синтаксис Intel или один из этих вопросов - 1 , 2 , 3 . Я попытался разобрать простейший пример C, который мог придумать, то есть глобальную переменную + return
из main()
- gcc -S test.c -fPIE -pie -fpie -m32
:
int var1 = 6;
int main() { return var1; }
, что в основном привело к:
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushl %ebp
Lcfi0:
.cfi_def_cfa_offset 8
Lcfi1:
.cfi_offset %ebp, -8
movl %esp, %ebp
Lcfi2:
.cfi_def_cfa_register %ebp
pushl %eax
calll L0$pb
L0$pb:
popl %eax
movl $0, -4(%ebp)
movl _var1-L0$pb(%eax), %eax
addl $4, %esp
popl %ebp
retl
.cfi_endproc
## -- End function
.section __DATA,__data
.globl _var1 ## @var1
.p2align 2
_var1:
.long 6 ## 0x6
.subsections_via_symbols
Это, очевидно, использует MOV в качестве LEA и почти такую же инструкцию, что и моя, за исключением -L0$pb
части, которая должна быть +/- подобна адресу _var1
- адресу L0$pb
, чтобы попасть в раздел .data
.
И все же, когда я пытаюсь использовать тот же подход с метками var1
и _main
, ничего:
.text
.global _main
_main:
xor %eax, %eax
xor %ebx, %ebx
#movl var1-_main(%ebp), %eax # EAX = 191
#movl var1-_main(%esp), %eax # EAX = 204
#movl var1-_main(%eax), %eax # segfault
ret
.data
var1: .long 6
.end
Есть идеи, что я делаю не так?
Edit:
Мне удалось вырезать ненужные вещи из дизассемблированного примера C и в итоге получилось:
.text
.global _main
_main:
pushl %ebp
pushl %eax
calll test
test:
popl %eax
/* var1, var2, ... */
movl var1-test(%eax), %eax
addl $4, %esp
popl %ebp
retl
/**
* how var1(label) - test(label) skips this label
* if it's about address subtracting?
*/
blobbbb:
xor %edx, %edx
.data
var1: .long 6
var2: .long 135
И для меня это не имеет особого смысла, потому что согласно этому руководству вызывающий должен 1) поместить параметры в стек (нет) 2) call
метка и callee должны фактически играть с ESP, EBP и другими регистрами. Кроме того, зачем мне нужен промежуточный ярлык или лучше сказать, есть ли способ без него?