Код: Выделить всё
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
Код: Выделить всё
/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
Код: Выделить всё
┌──────────────────────────────────────────────────────────────┐
│ 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 ?? ()
Когда я компилирую тот же код (за исключением пути 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
Я также хотел бы знать, если это printf сбой считается «ошибкой» (в этом случае мне нужно будет только выровнять %rsp при компиляции для Android), или то, что я делаю, определено в реализации (поэтому мне нужно делать это всегда, потому что это может сломаться в другой версии libc в Linux).
Кроме того, строка Hello из деструктора не печатается ни на Android, ни на Linux (из ./libMain.so), но печатается на Linux при запуске с Java (а не на Android).
Код: Выделить всё
Hello from constructorПодробнее здесь: https://stackoverflow.com/questions/798 ... red-object
Мобильная версия