Ответ 1
Выяснил это.:)
Операции с плавающей запятой на x86_64 используют векторные регистры xmm. Доступ к ним должен быть выровнен по границам 16 байт. Это объясняет, почему 32-битные платформы не подвергались воздействию, а работа с целыми и печатными символами работала.
Я скомпилировал свой код для сборки с помощью:
gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC
затем изменил функцию "my_main", чтобы иметь больше пространства стека.
До:
my_main:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %eax
movsd .LC1(%rip), %xmm0
movq %rax, %rdi
movl $1, %eax
call printf
movl $0, %edi
call _exit
.cfi_endproc
После того, как:
my_main:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
subq $8, %rsp ;;;;;;;;;;;;;;; ADDED THIS LINE
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %eax
movsd .LC1(%rip), %xmm0
movq %rax, %rdi
movl $1, %eax
call printf
movl $0, %edi
call _exit
.cfi_endproc
Затем я скомпилировал этот файл .S:
gcc list.S -o liblist.so -Wl,-e,my_main -shared
Это исправляет проблему, но я перенаправляю этот поток в списки рассылки GCC и GLIBC, поскольку это похоже на ошибку.
edit1:
В соответствии с noshadow в gcc irc это нестандартный способ сделать это. Он сказал, что если нужно использовать опцию gcc -e, либо инициализировать C runtime вручную, либо не использовать функции libc. Имеет смысл.