【问题标题】:find duplicate declared functions in c library (single files)在 c 库中查找重复的声明函数(单个文件)
【发布时间】:2017-02-17 22:00:15
【问题描述】:

我正在开发一个嵌入式项目,并且正在复制一个示例项目。 不考虑目标文件的链接顺序,我只是将c文件以随机顺序放在我的Makefile中。

编译和链接会产生 executable.elf1.9Mb。 没有生成错误,但可执行文件不起作用。

在没有解决方案的长时间搜索之后,我终于完全复制了该项目,包括 c 文件的顺序(其中 120 个),看我得到了 2.2Mbexecutable.elf 并且没有错误。并且可执行文件有效。

编译选项和/或链接选项没有任何变化。只是更改了 c 文件在 makefile 中列出的顺序,因此也更改了链接时目标文件的顺序。

我怀疑有多个具有不同主体/大小的重复函数实现。我的假设是链接器在链接时不记得以前的链接操作,只会选择它遇到的第一个操作而不会引发错误。

但是我想保留这个提供的库(所有单个 c 文件,没有库 *.a 文件)并找到重复的函数实现。所以我知道我应该按什么顺序提供 c 文件,更重要的是,为什么。

两个问题:

  1. 上面的描述确实是问题的潜在原因吗?
  2. 还有其他可能吗?
  3. 如何找到重复的函数实现?

很遗憾,正在编译的代码是专有的,目前无法共享详细信息。

编译器是:

 arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]

目标是:

 cortex-m3

感谢您的帮助。

--- 编辑 ---

有两个文件:

  1. 是包含所有源代码(source.mk)的列表:

     C_FILES_SRC  = $(SDK_DIR)/file001.c
     C_FILES_SRC += $(SDK_DIR)/file002.c
     C_FILES_SRC += $(SDK_DIR)/ .....
         |
     C_FILES_SRC += $(APPL_DIR)/file121.c
     C_FILES_SRC += $(APPL_DIR)/file122.c
    
  2. Makefile(短版):

    include source.mk
    CFLAGS = xxxxx
    # create objects
    %.o: %.c
        $(GCC) $(CFLAGS) -MMD -MP -MF($(@:%.o=%.d) -o $@ -c $<
    
    # link it all together
    executable.elf
        $(GCC) $(MAIN_CFLAGS) $(LINK_SCRIPTS) -Xlinker --gc-sections $(LIBS_DIR) $(EXTRA_LINK_FLAGS) $(SPECS) -o $@ $(OBJS) $(LIBS)
        $(SIZE) --format=berkeley $@
    

Makefile 我什么都没改变。只改变了 source.mk 中文件的顺序

【问题讨论】:

  • 我知道您说过您不能发布代码本身,但您可以发布与您的Makefile 相同的混淆代码吗?谢谢!事实上,我们甚至不知道您的 Makefile 的结构是什么,或者您使用什么构建系统来生成它(如果有的话)。这可能会让您更难为您提供明确的答案。
  • 你说'我的假设是......链接器......只是选择它遇到的第一个而不引发错误'。那将是非常不寻常的,也是错误的。如果有两个目标文件定义了相同的外部可见函数,则链接应该会失败并出现重复的函数错误。最简单的模拟方法是将一个目标文件添加到列表中两次;当你这样做时,链接应该会失败。你检查过目标文件的大小吗?您是否比较了两个二进制文件的size 输出?编译选项是否相同?编译器版本?
  • 我刚刚在我的应用程序中添加了一个任意库c 文件并编译/链接了它。所以有两个相同的目标文件具有不同的位置。链接器没有错误。
  • 刚刚在原始问题中添加了我的Makefiles 的简单版本。
  • 我的假设是基于我读到的here 在类 Unix 系统上,编译器和链接器的传统行为是在命令指定的目标文件中从左到右搜索外部函数行。

标签: c gcc linker embedded


【解决方案1】:

只有静态库(.a 或 .lib)表现出“第一次匹配解析”,因此链接顺序至关重要。由于 all 对象文件是显式链接的,如果存在重复符号,您会收到链接错误。因此,只有 .a/.lib 文件呈现给链接器的顺序才会产生这种效果。

也许您有两个不同版本的库,并且以不同的顺序链接它们?

GNU 工具链的 binutils 包括 nm 工具,用于检查对象和存档(库)文件中的符号。

另一种可能性是可执行入口点对您平台上的链接顺序很敏感;在这种情况下,它可能只是 crt0(或其他运行时启动代码)的链接顺序。

【讨论】:

  • 经过测试,我认为您的另一种可能性就是其中之一。将文件“startup_AMRCM0.S”放在列表的开头一切顺利,将“startup_AMRCM0.S”作为列表中的最后一个文件,链接出错。我检查了我使用相同的GCC 编译器工具链完成的其他项目,它们都在文件/对象列表的开头有启动代码,这是偶然的:-) 所以我以前从未遇到过这个问题。跨度>
  • 如果能在GNU ARM Embedded Toolchain 文档中找到有关此行为的确认信息会很高兴。如果我发现任何东西,我会在这里报告。
  • @Robert :来自多个项目的工具集合的问题是谁负责记录这些东西?这可能不是 GNU 工具链的内在问题。 Cortex-M3 从复位向量加载堆栈指针和起始地址 - 有很多方法可以确保它们与运行时启动代码中的 _reset 符号(或其他符号)匹配;可以强制链接描述文件中的位置,而不是依赖默认链接顺序。我记得很久以前在 GNU 上遇到过这个问题,这就是我提到它的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
相关资源
最近更新 更多