【问题标题】:GCC insert a static library containing assembly into a dynamic libGCC 将包含程序集的静态库插入到动态库中
【发布时间】:2017-08-16 14:30:09
【问题描述】:

我有一个问题:我有 2 个库(一个用 NASM 编译的 ASM 中的静态库和一个用 GCC 编译的 C 中的动态库)。

我首先在 ASM 中使用以下 Makefile 编译一个(我删除了部分以使其更具可读性):

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 $@ $<

然后我编译动态库,以便它使用静态的功能:

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);
    [...]
}

我收到此错误:

./a.out:符号查找错误:./libclib.so:未定义符号:asm_function

动态库上的纳米:

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

静态库上的纳米:

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

【问题讨论】:

  • 您能否在您的libclib.so 文件上调用nm 并在此处发布结果。
  • U asm_function: asm_function 被引用但未定义。
  • 我的asm_function 在静态库中。
  • 你能nm静态库和edit你的问题吗?
  • 改变了。

标签: c gcc assembly makefile shared-libraries


【解决方案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 相关,那么你就有一个non-relocatable code(一些汇编程序可以让它与 pc 相对一些指令,但这并不涵盖每条指令)。

为确保您在汇编中生成与位置无关的代码,请修改您的代码并将其反汇编,直到您在反汇编中看不到外部重定位。我不是 x86 专家,但我对 68k 家族做了很多。

【讨论】:

    【解决方案2】:

    这是不正确的:

    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 $@ $^ $(LIBS)
    

    顺序之所以重要是因为链接器只会解析在命令行参数中稍后定义的库中的符号,而不是它们被引用的位置。所以你所有的-l 标志通常应该在你所有的.o 文件之后。此规则不影响.o 文件,可以是任何顺序。

    这也不适用于所有链接器。

    (作为一个小提示,由于其特殊的缩进样式,我发现很难阅读 makefile — 标准化缩进样式的主要目的是让人们更容易在项目之间切换而无需“重新训练”他们的眼睛可以阅读新代码。当然,您可以继续使用任何有效的样式。$@$^ 的使用也是相当标准的。)

    【讨论】:

      猜你喜欢
      • 2011-04-14
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-29
      • 2017-08-05
      • 1970-01-01
      相关资源
      最近更新 更多