恰巧我正在研究這種類型的東西。 Linux下可執行文件和共享對象之間的主要區別之一是可執行文件具有解釋器和(有效)入口點。 例如,在一個最小的程序:
$ echo 'int main;' | gcc -xc -
如果你看一下它的精靈程序標題:
$ readelf --program-headers a.out
...
INTERP 0x0000000000000200 0x0000000000400200 0x0000000000400200
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
...
解釋程序負責程序的執行,來實現這一點,它會執行一些初始化,如加載所需的共享對象。實際上,這與劇本shebang非常類似,但是對於elf文件。 在這種情況下,/lib64/ld-linux-x86-64.so.2是amd64的加載程序。你可以有倍數裝載機:例如,一個用於32位,一個是64
現在的切入點:
$ readelf --file-header a.out
ELF Header:
...
Entry point address: 0x4003c0
...
$ readelf -a a.out | grep -w _start
57: 00000000004003c0 0 FUNC GLOBAL DEFAULT 13 _start
默認情況下,你可以看到_start被定義爲切入點。
所以,如果你考慮下面的小例子:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef INTERPRETER
const char interp[] __attribute__((section(".interp"))) = INTERPRETER;
#endif /* INTERPRETER */
void entry_point(void) {
fprintf(stderr, "hello executable shared object world !\n");
_exit(EXIT_SUCCESS);
}
如果你編譯它作爲一個「正常」的共享對象並執行:
$ gcc libexecutable.c -Wall -Wextra -fPIC -shared -o libexecutable.so
$ ./libexecutable.so
Erreur de segmentation
你可以看到它出現segfaults。但是現在,如果你定義一個解釋器(適應它的路徑是什麼readelf --program報頭之前給你),並告訴鏈接什麼是你的切入點:
$ gcc libexecutable.c -Wall -Wextra -fPIC -shared -o libexecutable.so -DINTERPRETER=\"/lib64/ld-linux-x86-64.so.2\" -Wl,-e,entry_point
$ ./libexecutable.so hello executable shared object world !
現在它的工作原理。請注意,_exit()調用對於在執行結束時避免段錯誤是必要的。
但最後,請記住,因爲您指定了一個自定義入口點,您將根據需要繞過可能需要或不需要的libc初始化步驟。
您的'gcc'設置爲ARM編譯?我不認爲你可以將x86可執行文件移植到ARMv7a設備上,並期望它可以正常工作。在x86安卓設備(例如模擬器)上嘗試它,或嘗試編譯目標處理器的體系結構。 – initramfs
@CPUTerminator,都是x86。 – drdot
嗯,我沒有太多可靠的依據,也許gcc使用的是不支持Android的指令/擴展。看看這個[鏈接](http://shareprogrammingtips.com/c-language-programming-tips/cross-compile-cc-based-programs-run-android-smart-phones/),而方法1似乎是與您的做法相同,它針對的是ARM體系結構。也許嘗試方法2和/或3? – initramfs