Проблемы с libc Android (Linux) при создании исполняемого общего объектаLinux

Ответить
Anonymous
 Проблемы с libc Android (Linux) при создании исполняемого общего объекта

Сообщение Anonymous »

У меня есть 2 файла:

Код: Выделить всё

crt.c:
const char service_interp[] __attribute__((section(".interp"))) = "${LD_SO}";

extern void _exit (int __status) __attribute__ ((__noreturn__));
int main();

void _start() {
_exit(main());
}

Код: Выделить всё

Main.c:
#include 
#include 
#include 
#include 
jint Java_Main_Main(JNIEnv*,jclass);
int main() {
const char * str = "Hello from executable\n";
write(1,str,strlen(str));
return Java_Main_Main(NULL,NULL);
}

__attribute__((constructor)) void init() {
printf("Hello from constructor\n");
}

__attribute__((destructor)) void fin() {
printf("Hello from destructor");
}

jint Java_Main_Main(JNIEnv * env, jclass Main) {
printf("Hello from shared object\n");
return 0;
}
с помощью которого я компилирую

Код: Выделить всё

clang version 21.1.6
Target: x86_64-unknown-linux-android24
Thread model: posix
InstalledDir: /data/data/com.termux/files/usr/bin

Код: Выделить всё

sed "s/\${LD_SO}/$(./getldso.sh | sed "s/\//\\\\\//g")/g"  crt.c | clang -x c - -c -fPIC -o crt.o

clang Main.c -g -fPIC -o libMain.so -DLD_SO=$(./getldso.sh) crt.o -shared
getldso.sh находит и печатает путь к системному компоновщику (

Код: Выделить всё

/system/bin/linker64
здесь)
Если я загружаю файл с помощью Java System.loadLibrary или C dlopen, он печатается правильно

Код: Выделить всё

Hello from constructor
Hello from shared object
Hello from destructor // only in C if I use `dlclose`
Но если я попытаюсь его выполнить (

Код: Выделить всё

./libMain.so
) не получается:

Код: Выделить всё

Hello from constructor
Hello from executable
Segmentation fault
Пытаясь отладить его, я обнаружил, что он выдает ошибку segfault во втором вызове printf

Код: Выделить всё

┌──────────────────────────────────────────────────────────────┐
│   0x7ffff7a9f6e0  push   %rbp                                │
│   0x7ffff7a9f6e1  mov    %rsp,%rbp                           │
│   0x7ffff7a9f6e4  push   %r14                                │
│   0x7ffff7a9f6e6  push   %rbx                                │
│   0x7ffff7a9f6e7  sub    $0xd0,%rsp                          │
│   0x7ffff7a9f6ee  mov    %rdi,%rbx                           │
│   0x7ffff7a9f6f1  mov    %rsi,-0xd8(%rbp)                    │
│   0x7ffff7a9f6f8  mov    %rdx,-0xd0(%rbp)                    │
│   0x7ffff7a9f6ff  mov    %rcx,-0xc8(%rbp)                    │
│   0x7ffff7a9f706  mov    %r8,-0xc0(%rbp)                     │
│   0x7ffff7a9f70d  mov    %r9,-0xb8(%rbp)                     │
│   0x7ffff7a9f714  test   %al,%al                             │
│   0x7ffff7a9f716  je     0x7ffff7a9f741                      │
│   0x7ffff7a9f718  movaps %xmm0,-0xb0(%rbp)                   │
│   0x7ffff7a9f71f  movaps %xmm1,-0xa0(%rbp)                   │
│   0x7ffff7a9f726  movaps %xmm2,-0x90(%rbp)                   │
│   0x7ffff7a9f72d  movaps %xmm3,-0x80(%rbp)                   │
│   0x7ffff7a9f731  movaps %xmm4,-0x70(%rbp)                   │
│   0x7ffff7a9f735  movaps %xmm5,-0x60(%rbp)                   │
│   0x7ffff7a9f739  movaps %xmm6,-0x50(%rbp)                   │
│   0x7ffff7a9f73d  movaps %xmm7,-0x40(%rbp)                   │
│   0x7ffff7a9f741  mov    %fs:0x28,%rax                       │
│   0x7ffff7a9f74a  mov    %rax,-0x18(%rbp)                    │
│   0x7ffff7a9f74e  xorps  %xmm0,%xmm0                         │
│  >0x7ffff7a9f751  movaps %xmm0,-0x30(%rbp)                   │
│   0x7ffff7a9f755  lea    -0xe0(%rbp),%rax                    │
│   0x7ffff7a9f75c  mov    %rax,-0x20(%rbp)                    │
│   0x7ffff7a9f760  movabs $0x3000000008,%rax                  │
│   0x7ffff7a9f76a  mov    %rax,-0x30(%rbp)                    │
│   0x7ffff7a9f76e  lea    0x10(%rbp),%rax                     │
│   0x7ffff7a9f772  mov    %rax,-0x28(%rbp)                    │
│   0x7ffff7a9f776  mov    0x655b3(%rip),%rax # 0x7ffff7b04d30 │
│   0x7ffff7a9f77d  mov    (%rax),%r14                         │
│   0x7ffff7a9f780  mov    0x58(%r14),%rdi                     │
│   0x7ffff7a9f784  cmpb   $0x0,0x60(%rdi)                     │
│   0x7ffff7a9f788  jne    0x7ffff7a9f793                      │
│   0x7ffff7a9f78a  add    $0x38,%rdi                          │
│   0x7ffff7a9f78e  call   0x7ffff7afd9d0                      │
└──────────────────────────────────────────────────────────────┘
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a9f751 in ?? ()
и регистр %rbp имеет значение 0x7ffffffdad8, поэтому %rbp-0x30 не выровнен по 16 битам, что приводит к выдаче ошибки segfault.
Когда я компилирую тот же код (за исключением пути ld.so, который мне нужно передать -I /usr/lib/jvm/java-25-openjdk-amd64/include -iquote /usr/lib/jvm/java-25-openjdk-amd64/include/linux при компиляции) в Linux код выполняется правильно.
версия clang:

Код: Выделить всё

$ clang -v
Ubuntu clang version 18.1.3 (1ubuntu1)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/i686-linux-gnu/14
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/13
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/14
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/14
Candidate multilib: .;@m64
Selected multilib:  .;@m64
Достаточно ли выравнивания %rsp в _start, чтобы функции libc работали (это исправило printf на Android), или это просто «хакерское» исправление, которое не решает основную проблему, и мне нужно сделать что-то еще/больше (возможно, вызвать какую-то функцию __libc_init)?
Я также хотел бы знать, если это printf сбой считается «ошибкой» (в этом случае мне нужно будет только выровнять %rsp при компиляции для Android), или то, что я делаю, определено в реализации (поэтому мне нужно делать это всегда, потому что это может сломаться в другой версии libc в Linux).
Кроме того, строка Hello из деструктора не печатается ни на Android, ни на Linux (из ./libMain.so), но печатается на Linux при запуске с Java (а не на Android).

Код: Выделить всё

Hello from constructor
вызывается везде, кроме Linux из ./libMain.so.

Подробнее здесь: https://stackoverflow.com/questions/798 ... red-object
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Linux»