2017-03-23 62 views
1

我遇到了一個問題:我有2個庫(在NASM中編譯的ASM中的靜態和使用GCC編譯的C中的動態庫)。GCC將包含程序集的靜態庫插入到動態庫中

我首先將一個編譯與下面的Makefile ASM(I去除部分,使其更具有可讀性):

ASM    = nasm 
NAME   = libasmlib.a 
SRC    = [...all .asm files...] 
OBJ    = $(SRC:.asm=.o) 
FLAGS   = -f elf64 -g 

all    : $(NAME) 

$(NAME)   : $(OBJ) 
        ar rc $(NAME) $(OBJ) 
        ranlib $(NAME) 

%.o : %.asm 
        $(ASM) $(FLAGS) -o [email protected] $< 

然後我編譯動態庫,以便它使用靜態的功能:

CC     = gcc 
NAMEDYN    = libclib.so 
SRC     = [...all .c files...] 
OBJ     = $(SRC:%.c=%.o) 
CFLAGS    = -W -Wall -Werror -pedantic -fPIC 
LDFLAGS    = -L./libs/ASM -lasmlib 

$(NAME)    : $(OBJ) 
         $(CC) $(LDFLAGS) -shared -o $(NAMEDYN) $(OBJ) 

all     : $(NAME) 

我沒有問題,一切都完美地編譯,但是當我測試的代碼具有以下.C(與GCC maindyn.c -ldl):

#include <stdio.h> 
#include <dlfcn.h> 

int     main(int ac, char **av) 
{ 
    int    res; 
    void   *handle; 
    int    (*c_function)(char *str); 

    if (!(handle = dlopen("./libclib.so", RTLD_LAZY | RTLD_GLOBAL | RTLD_NOW))) 
     return 1; 
    c_function = dlsym(handle, "c_function"); 

    res = c_function("Hi!"); 
    printf("%d\n", res); 
    [...] 
} 

我得到這個錯誤:在靜態庫

    U asm_function 
0000000000202078 B __bss_start 
0000000000202078 b completed.7558 
<snip> 
0000000000000ee0 T c_function 
0000000000000e20 t register_tm_clones 
       U [email protected]@GLIBC_2.4 
0000000000202078 d __TMC_END__ 

處:在動態LIB

./a.out: symbol lookup error: ./libclib.so: undefined symbol: asm_function

納米

asm_function.o: 
0000000000000000 T asm_function 
000000000000001c t _end 
0000000000000021 t _finded 
0000000000000008 t _loop 
+0

你可以在你的'libclib.so '文件並在這裏​​發佈結果。 –

+0

'U asm_function':'asm_function'被引用但未定義。 –

+0

我的'asm_function'進入了靜態庫。 – DarkyZ

回答

1

在創建動態庫(或一般鏈接),依賴關係的順序重要。你的makefile的

部分:

$(NAME)    : $(OBJ) 
         $(CC) $(LDFLAGS) -shared -o $(NAMEDYN) $(OBJ) 

構建線擴展(大約)至:

gcc -L./libs/ASM -lasmlib -shared -o libdyn.so obj1.o obj2.o 

問題是,asm_function.a文件中定義,但在.o的一個使用文件。你必須把.a文件.o文件,否則將被忽略(鏈接對象必須從最依賴的對象開始至少依賴對象)

我把鏈接標誌到底這樣的靜庫在結尾處:

$(NAME)    : $(OBJ) 
         $(CC) -shared -o $(NAMEDYN) $(OBJ) $(LDFLAGS) 

解決了符號解析問題,但解決了位置無關的代碼問題。

使用C語言,沒有什麼比設置-fPIC選項更容易(實際上,它是默認的「現代」編譯器,所以不需要打擾),但彙編語言沒有那個高級層。如果你加載了一個有效的地址,並且你沒有使它成爲pc-relative,你有一個non-relocatable code(一些彙編器可以使它對某些指令是pc-relative,但是不包括每條指令)。

爲了確保您在彙編中生成與位置無關的代碼,請修改您的代碼並將其反彙編,直到您在反彙編中看不到外部重定位代碼。我不是x86專家,但我已經在68k家族中做了很多。

1

這是不正確的:

LDFLAGS    = -L./libs/ASM -lasmlib 

$(NAME)    : $(OBJ) 
         $(CC) $(LDFLAGS) -shared -o $(NAMEDYN) $(OBJ) 

的順序很重要。按說,-L-l參數不應該是LDFLAGS(連接標誌)的一部分,但的LIBS(庫),這似乎在命令行按以下順序部分:

# No interesting LDFLAGS now, but maybe you want --gc-sections or --as-needed 
LDFLAGS = 
# Libraries go here 
LIBS = -L./libs/ASM -lasmlib 

libclib.so: $(OBJ) 
    $(CC) $(LDFLAGS) -shared -o [email protected] $^ $(LIBS) 

之所以順序是重要的因爲鏈接器只會解析在命令行參數中定義的後面的庫中的符號,而不是它們被引用的位置。所以你所有的-l標誌通常應該在你所有的.o文件之後。此規則不會影響.o文件,文件可以按任意順序排列。

這也不適用於所有連接器。 (作爲一個小問題,由於其特有的縮進樣式,我發現難以閱讀makefile - 標準化縮進樣式的主要目的是爲了讓人們更容易在不需要「重新訓練」的情況下在項目之間切換「他們的眼睛看新的代碼,當然你可以繼續使用任何風格的作品,[email protected]$^也是相當標準的。)

相關問題