eCos疑问——两个cyg_user_start函数

mingdu.zheng <at> gmail <dot> com
http://blog.csdn.net/zoomdy/article/details/12622639

 

两个cyg_user_start函数

在阅读eCos代码的过程中发现整个系统定义了两个cyg_user_start函数,一个位于packages /infra /<version> /src /userstart.cxx:72,另一个位于packages /language /c /libc /startup /<version> /src /cstartup.cxx:117,两个函数均被声明为弱符号(__attribute__((weak)))。

如果用户代码重定义cyg_user_start函数,那么这两个弱符号均被丢弃,不会有任何疑问。

如果用户代码没有重定义cyg_user_start函数,那么在链接过程到底是链接哪个符号呢?毕竟两个都是弱符号,在地位上是等价的。

查看相应的cdl文件发现前一个cyg_user_start函数编译进libtarget.a,

#packages/infra/<version>/cdl/infra.cdl:59
compile startup.cxx prestart.cxx pkgstart.cxx userstart.cxx        \
        dummyxxmain.cxx null.cxx simple.cxx fancy.cxx buffer.cxx   \
        diag.cxx tcdiag.cxx memcpy.c memset.c delete.cxx eprintf.c \
        pure.cxx gccsupport.cxx

后一个cyg_user_start函数编译进默认的libextras.a,libextras.a最终被编译成extras.o,

#packages/language/c/libc/startup/<version>/cdl/startup.cdl:75
compile -library=libextras.a cstartup.cxx

查看target.ld文件,发现extras.o的定义位于libtarget.a之前,而gcc/ld链接过程中符号查找次序是跟文件出现的次序有关,也就是优先选择出现在前面文件中的符号。

#target.ld
STARTUP(vectors.o)
ENTRY(reset_vector)
INPUT(extras.o)
GROUP(libtarget.a libgcc.a libsupc++.a)

谜团这就解开了,eCos将会链接到C库中的cyg_user_start,除非用户重定义cyg_user_start或C库中的cyg_user_start因为选项未满足而被屏蔽,才会链接到infra中的cyg_user_start。

 

验证gcc/ld符号查找次序

gcc/ld查找弱符号的次序与输入文件次序有关,为了验证这点,创建三个源文件。

// weak1.c
#include <stdio.h>
void foo(void) __attribute__((weak));
void foo(void)
{
    printf("foo from weak1.c\n");
}
// weak2.c
#include <stdio.h>
void foo(void) __attribute__((weak));
void foo(void)
{
    printf("foo from weak2.c\n");
}
// main.c
#include <stdlib.h>
void foo(void);
int main(void)
{
    foo();
    return EXIT_SUCCESS;
}

在linux下分别将这三个文件编译成.o文件,不能在cygwin环境下编译,只有ELF文件格式才支持弱符号,cygwin环境下的.o文件使用COFF格式,不支持弱符号。

gcc -c -Wall -o weak1.o weak1.c
gcc -c -Wall -o weak2.o weak2.c
gcc -c -Wall -o main.o main.c

将这3个.o文件链接成可执行文件,首先将weak1.o放前面,可以看到编译后的可执行文件调用的是weak1.c中的foo函数。然后将weak2.o放前面,可以看到编译后的可执行文件调用的是weak2.c中的foo函数。

gcc -o a.out main.o weak1.o weak2.o
./a.out
foo from weak1.c
gcc -o a.out main.o weak2.o weak1.o
./a.out
foo from weak2.c

如果将weak1.c,weak2.c函数声明的__attribute__((weak))去掉,再重新编译链接,将导致下述错误。只有弱符号可以重复定义,非弱符号重复定义将导致链接错误。

weak1.o: In function `foo':
weak1.c:(.text+0x0): multiple definition of `foo'
weak2.o:weak2.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status

gcc/ld对其它符号的查找过程同样跟文件次序有关,包括从命令行输入的文件和通过ldscript指定的文件,一般情况下对输入文件仅查找一次,除非将文件放在--start-group和--end-group选项之间,或者放在ldscript的GROUP指令内,被group过的文件将会被重复查找直到所有符号均已解析。如果链接过程中出现符号未解析错误但是确实已经定义了该符号,那么看看文件次序是否正确,或者将文件group处理以递归解析符号。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值