【问题标题】:Android dynamic linked library unable to resolve symbols of main programAndroid动态链接库无法解析主程序符号
【发布时间】:2011-11-04 23:01:29
【问题描述】:

我可以成功地用 C 语言创建一个链接到库的程序,并且能够调用该库的函数。如果该库从主程序调用函数,则会出现错误:

root@android:/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

代码在两个 C 文件中,我还包含 Makefile。 hello.c 是包含由 main.c(主程序)调用的函数 hello 的库。函数 hello 尝试调用函数 crossfunction 并且在 android 中不起作用(在 Linux 中它工作得很好)。我怀疑来自 android 链接器,但到目前为止还没有证据(请参阅https://android.googlesource.com/platform/bionic/+/froyo-release/linker/README.TXT)。

另一个好的提示可能是 libhello.so 文件中交叉函数的 readelf 输出中的 NOTYPE 赋值。请看下文。

         5: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND crossfunction

编译器标志或链接器标志中可能有任何提示?

::::::::::::::
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();
}

为了编译,我使用了带有 android ndk https://github.com/nitomartinez/agcc 的 agcc 包装器

这是 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) "

我查看了 readelf 位,但我发现 .dynsym、.rel.plt 和 .symtab 部分没有实质性差异。

为你好世界

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
...

对于 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

【问题讨论】:

    标签: android linker linker-errors


    【解决方案1】:

    从 2.0 版开始,Android 遵循 RTLD_LOCAL 共享库语义。这意味着库中的符号不​​可用于随后加载的库。你必须把你的主程序变成一个 .so 库,并明确地将它链接到 libhelloworld.so 。请参阅this thread 了解更多信息。

    请注意,Android 动态链接器与 Linux 不同。请务必在不同版本的模拟器上测试您的应用(从 Api 3 开始),因为这些机制会随着时间而变化。

    【讨论】:

    • 感谢您的确认,我怀疑在某种程度上。也感谢您指出线程。
    猜你喜欢
    • 2016-01-19
    • 1970-01-01
    • 2013-06-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    相关资源
    最近更新 更多