如何在GCC+CMake环境下为全局外部结构体字段创建全局符号别名
解决GCC+CMake下为结构体成员创建全局符号别名的问题
为什么你之前的方法失败
GCC的__attribute__((alias("MyObject.mydata")))语法没法用,是因为这个属性要求别名必须指向独立的全局符号,但MyObject.mydata只是结构体里的成员,不是单独的全局符号,链接器根本认不出这个格式的符号名,所以才报"aliased to undefined symbol"。
可行方案一:用链接器--defsym选项(推荐)
这个方法不需要额外写脚本,直接通过CMake传递链接参数就能搞定:
计算结构体成员偏移量
在CMakeLists.txt里加一段代码,调用GCC预处理器从头文件里算出mydata在结构体里的偏移值:execute_process( COMMAND gcc -E -P -x c -include object.h - <<EOF #include <stddef.h> offsetof(struct MyObjectStruct_s, mydata) EOF OUTPUT_VARIABLE MYDATA_OFFSET OUTPUT_STRIP_TRAILING_WHITESPACE )传递链接选项定义别名
给你的可执行目标加上链接参数,直接把var_alias定义成MyObject加偏移的地址:target_link_options(你的可执行目标名 PRIVATE "-Wl,--defsym=var_alias=MyObject+${MYDATA_OFFSET}")记得把
你的可执行目标名换成实际的CMake目标名称。
可行方案二:用链接脚本
如果偏好链接脚本的方式,也可以这么做:
编写链接脚本
先算出mydata的偏移量(可以用上面CMake的方法,或者写个小C程序编译运行输出offsetof结果),然后创建一个比如alias_script.ld的文件:PROVIDE(var_alias = MyObject + 0x0); # 把0x0换成你算出的实际偏移量在CMake中指定链接脚本
把这个脚本加入链接选项:target_link_options(你的可执行目标名 PRIVATE -T ${CMAKE_SOURCE_DIR}/alias_script.ld)
验证结果
编译完成后,运行readelf -s 你的可执行文件名 | grep var_alias,就能在符号表里找到var_alias,它的地址和MyObject.mydata完全一致,符合你的要求。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

