2011-08-27 23 views
5

Tôi có thể tạo thành công chương trình trong C liên kết đến thư viện và có thể gọi các chức năng của thư viện đó. Nếu thư viện đó gọi một hàm từ chương trình chính, lỗi sẽ phát sinh:Thư viện liên kết động Android không thể giải quyết các biểu tượng của chương trình chính

[email protected]:/data/local/tmp # ./helloworld          
link_image[1966]: 637 could not load needed library 'libhello.so' for './helloworld' (reloc_library[1315]: 637 cannot locate 'crossfunction'...) CANNOT LINK EXECUTABLE 

Mã nằm trong hai tệp C và tôi cũng bao gồm Makefile. hello.c là thư viện chứa hàm hello được gọi bởi main.c (chương trình chính). Hàm hello cố gắng gọi hàm crossfunction và không hoạt động trong android (trong Linux nó hoạt động hoàn toàn tốt). Tôi nghi ngờ từ liên kết android, nhưng không có bằng chứng cho đến nay (xin vui lòng xem https://android.googlesource.com/platform/bionic/+/froyo-release/linker/README.TXT).

Một gợi ý tốt khác có thể là gán NOTYPE trong đầu ra đọc cho giao diện trong tệp libhello.so. Vui lòng xem bên dưới.

  5: 00000000  0 NOTYPE GLOBAL DEFAULT UND crossfunction 

Bất kỳ gợi ý nào có thể trong cờ trình biên dịch hoặc cờ liên kết?

:::::::::::::: 
main.c 
:::::::::::::: 
#include <stdio.h> 
extern void hello(const char* name); 
int main(void) { 
    hello("World!"); 
} 

void crossfunction(void) { 
    printf("This is called from the library\n"); 
} 
:::::::::::::: 
hello.c 
:::::::::::::: 
#include <stdio.h> 
extern void crossfunction(void); 
static char *s;  
void hello(const char* name) { 
    s = "my second name"; 
    printf("Hello %s %s!\n", s, name); 
    crossfunction(); 
} 

Để biên dịch tôi sử dụng wrapper AGCC với ndk android https://github.com/nitomartinez/agcc

Đây là Makefile:

OBJECTS=main.o 
LIB=libhello.so 
LIBOBJ=hello.o 
TARGET=helloworld 
TARGETDIR=/data/local/tmp 
CC=agcc 

.PHONY: all install run clean distclean 

all: $(TARGET) $(LIB) 

hello.o: hello.c Makefile 
    $(CC) $(CFLAGS) -c -o hello.o hello.c 

$(TARGET): $(OBJECTS) $(LIB) Makefile 
    $(CC) -Wl,-rpath=$(TARGETDIR) -lhello -L . -o $(TARGET) $(OBJECTS) 

$(LIB): $(LIBOBJ) Makefile 
    $(CC) -shared -o $(LIB) $(LIBOBJ) 

install: $(TARGET) 
    adb push $(TARGET) $(TARGETDIR)/$(TARGET) 
    adb push $(LIB) $(TARGETDIR)/$(LIB) 

run: install 
    adb shell "export LD_LIBRARY_PATH=$(TARGETDIR); $(TARGETDIR)/$(TARGET) " 

tôi đã có một cái nhìn tại các bit readelf, nhưng tôi thấy không có sự khác biệt đáng kể trong các phần .dynsym, .rel.plt và .symtab.

Đối helloworld

Relocation section '.rel.plt' at offset 0x33c contains 3 entries: 
Offset  Info Type   Sym.Value Sym. Name 
0000954c 00000416 R_ARM_JUMP_SLOT 00008368 hello 
00009550 00000516 R_ARM_JUMP_SLOT 00008374 puts 
00009554 00000816 R_ARM_JUMP_SLOT 00008380 __libc_init 

Symbol table '.dynsym' contains 16 entries: 
    Num: Value Size Type Bind Vis  Ndx Name 
    0: 00000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 000083b0 32 FUNC GLOBAL DEFAULT 7 crossfunction 
    2: 00008450  0 NOTYPE GLOBAL DEFAULT ABS __exidx_end 
    3: 00009558  0 NOTYPE GLOBAL DEFAULT ABS _bss_end__ 
    4: 00008368  0 FUNC GLOBAL DEFAULT UND hello 
    5: 00008374  0 FUNC GLOBAL DEFAULT UND puts 
... 
Symbol table '.symtab' contains 62 entries: 
    Num: Value Size Type Bind Vis  Ndx Name 
... 
    41: 000083b0 32 FUNC GLOBAL DEFAULT 7 crossfunction 
    42: 00008450  0 NOTYPE GLOBAL DEFAULT ABS __exidx_end 
    43: 00009558  0 NOTYPE GLOBAL DEFAULT ABS _bss_end__ 
    44: 00008368  0 FUNC GLOBAL DEFAULT UND hello 
    45: 00008374  0 FUNC GLOBAL DEFAULT UND puts 
... 
    55: 00008390 32 FUNC GLOBAL DEFAULT 7 main 
... 

Và đối với libhello.so

Relocation section '.rel.plt' at offset 0xae8 contains 7 entries: 
Offset  Info Type   Sym.Value Sym. Name 
000032cc 00000516 R_ARM_JUMP_SLOT 00000000 crossfunction 
000032d0 00000616 R_ARM_JUMP_SLOT 00000000 printf 
000032d4 00000f16 R_ARM_JUMP_SLOT 00000000 __cxa_begin_cleanup 
000032d8 00001516 R_ARM_JUMP_SLOT 00000000 memcpy 
000032dc 00001f16 R_ARM_JUMP_SLOT 00000000 abort 
... 

Symbol table '.dynsym' contains 64 entries: 
    Num: Value Size Type Bind Vis  Ndx Name 
    0: 00000000  0 NOTYPE LOCAL DEFAULT UND 
... 
    5: 00000000  0 NOTYPE GLOBAL DEFAULT UND crossfunction 
    6: 00000000  0 FUNC GLOBAL DEFAULT UND printf 
... 
    19: 00000b88 100 FUNC GLOBAL DEFAULT 7 hello 
    21: 00000000  0 FUNC GLOBAL DEFAULT UND memcpy 
... 

Symbol table '.symtab' contains 138 entries: 
    Num: Value Size Type Bind Vis  Ndx Name 
    25: 00000000  0 FILE LOCAL DEFAULT ABS hello.c 
    79: 00000000  0 NOTYPE GLOBAL DEFAULT UND crossfunction 
    80: 00000000  0 FUNC GLOBAL DEFAULT UND printf 

Trả lời

3

Từ phiên bản 2.0 Android theo ngữ nghĩa thư viện RTLD_LOCAL chia sẻ. Có nghĩa là các biểu tượng trong thư viện không có sẵn cho các thư viện được tải sau đó. Bạn phải biến chương trình chính của bạn thành một thư viện .so và liên kết đến libhelloworld.so một cách rõ ràng. Xem this thread để biết thêm thông tin.

Lưu ý rằng trình liên kết động Android khác với trình liên kết Linux. Hãy chắc chắn kiểm tra các ứng dụng của bạn trên trình mô phỏng các phiên bản khác nhau (bắt đầu từ Api 3), vì các cơ chế đã thay đổi theo thời gian.

+0

Cảm ơn bạn đã xác nhận điều đó, tôi nghi ngờ rằng theo một cách nào đó. Cảm ơn bạn đã chỉ ra chuỗi đó. – Nito

Các vấn đề liên quan