静态库代码对驻留在应用程序代码中的外部结构使用了错误的地址
Static library code uses wrong address for extern struct residing in application code
我这边出现了非常奇怪的错误。我正在为 Cortex-M4f 运行 Nucleus RTOS 编写固件。对于我的应用程序,我有一些预构建的静态库(例如 libexternal.a),它们需要一个必须由应用程序提供的全局结构(在静态库中声明为 extern)。
在我的应用程序代码中,我可以很好地访问该结构,但在静态库的代码中,我总是会遇到 HardFault 中断。
通过调试我发现处理器试图访问错误地址上的结构。这是一些示例伪代码:
appconfig.c
struct AppConfiguration g_appconfig = {
/* initialize everything statically */
};
main.c
include <staticlib.h>
void main(){
g_appconfig.somemember = 1 /* this works */
staticlib_lib_init();
}
下面的所有内容都是静态库的一部分,并且在编译应用程序之前预先构建。
appconfig.h
struct AppConfiguration{
uint32_t somemember;
};
staticlib.h
#include "appconfig.h"
extern struct AppConfiguration g_appconfig;
void static_lib_init();
staticlib.c
#include "staticlib.h"
void static_lib_init(){
g_appconfig.somemember = 1 /* causes a HardFault */
}
静态库编译标志:
-ffunction-sections
-fdata-sections
-fno-builtin-memcpy
-DARM_MATH_CM4=1
-mthumb
-mcpu=cortex-m4
-mfloat-abi=soft
-fPIC
-Wno-unused-but-set-variable
以及带有标志的应用程序:
-ffunction-sections
-fdata-sections
-fno-builtin-memcpy
-mthumb
-mcpu=cortex-m4
-g
-mfloat-abi=soft
通过调试我发现静态库试图在错误的内存地址访问g_appconfig。例如
g_appconfig 从地址 0x2000061c 开始,static_lib_init() 尝试在地址 0xff7f4342 访问它。我的 SRAM 从 0x2000000 开始是 320k,我的 ROM 从 0x8000000 开始是 2MB。所以访问 0xff 处的内存是没有意义的......(可能是一些硬件寄存器或其他任何东西)。
static_lib_init() 的反汇编如下所示:
00000000 <static_lib_init>:
0: b5f0 push {r4, r5, r6, r7, lr}
2: b08f sub sp, #60 ; 0x3c
4: af06 add r7, sp, #24
6: 6178 str r0, [r7, #20]
8: 6139 str r1, [r7, #16]
a: 60fa str r2, [r7, #12]
c: 60bb str r3, [r7, #8]
e: 4cf9 ldr r4, [pc, #996] ; (3f4 <static_lib_init+0x3f4>)
10: 447c add r4, pc
12: 4bf9 ldr r3, [pc, #996] ; (3f8 <static_lib_init+0x3f8>)
14: 58e3 ldr r3, [r4, r3]
16: 461a mov r2, r3
18: 2301 movs r3, #1
1a: f8c2 30d0 str.w r3, [r2, #208] ; 0xd0
r2
应该包含 g_appconfig
的起始地址(#208 是我想要在真实世界代码中访问的元素的偏移量),但是在调试时包含 0xff7f4342.
知道这是怎么发生的吗?链接器不应该在链接时替换生成的静态库中 g_appconfig 的地址吗?
如果我自己无法测试,我无法给你一个肯定的答案,但我猜问题是你正在用 -fPIC
构建你的库,但你的主要应用不是。
请记住,当您要求编译器生成与位置无关的代码时,您也在要求它生成与位置无关的数据。在您的情况下,全局变量 g_appconfig
将位于链接器确定的固定位置。
尝试删除库构建中的 -fPIC
选项。由于您只是静态链接,所以您并不真正需要它,而且它更有可能损害您的性能而不是帮助。
我这边出现了非常奇怪的错误。我正在为 Cortex-M4f 运行 Nucleus RTOS 编写固件。对于我的应用程序,我有一些预构建的静态库(例如 libexternal.a),它们需要一个必须由应用程序提供的全局结构(在静态库中声明为 extern)。
在我的应用程序代码中,我可以很好地访问该结构,但在静态库的代码中,我总是会遇到 HardFault 中断。
通过调试我发现处理器试图访问错误地址上的结构。这是一些示例伪代码:
appconfig.c
struct AppConfiguration g_appconfig = {
/* initialize everything statically */
};
main.c
include <staticlib.h>
void main(){
g_appconfig.somemember = 1 /* this works */
staticlib_lib_init();
}
下面的所有内容都是静态库的一部分,并且在编译应用程序之前预先构建。
appconfig.h
struct AppConfiguration{
uint32_t somemember;
};
staticlib.h
#include "appconfig.h"
extern struct AppConfiguration g_appconfig;
void static_lib_init();
staticlib.c
#include "staticlib.h"
void static_lib_init(){
g_appconfig.somemember = 1 /* causes a HardFault */
}
静态库编译标志:
-ffunction-sections
-fdata-sections
-fno-builtin-memcpy
-DARM_MATH_CM4=1
-mthumb
-mcpu=cortex-m4
-mfloat-abi=soft
-fPIC
-Wno-unused-but-set-variable
以及带有标志的应用程序:
-ffunction-sections
-fdata-sections
-fno-builtin-memcpy
-mthumb
-mcpu=cortex-m4
-g
-mfloat-abi=soft
通过调试我发现静态库试图在错误的内存地址访问g_appconfig。例如
g_appconfig 从地址 0x2000061c 开始,static_lib_init() 尝试在地址 0xff7f4342 访问它。我的 SRAM 从 0x2000000 开始是 320k,我的 ROM 从 0x8000000 开始是 2MB。所以访问 0xff 处的内存是没有意义的......(可能是一些硬件寄存器或其他任何东西)。
static_lib_init() 的反汇编如下所示:
00000000 <static_lib_init>:
0: b5f0 push {r4, r5, r6, r7, lr}
2: b08f sub sp, #60 ; 0x3c
4: af06 add r7, sp, #24
6: 6178 str r0, [r7, #20]
8: 6139 str r1, [r7, #16]
a: 60fa str r2, [r7, #12]
c: 60bb str r3, [r7, #8]
e: 4cf9 ldr r4, [pc, #996] ; (3f4 <static_lib_init+0x3f4>)
10: 447c add r4, pc
12: 4bf9 ldr r3, [pc, #996] ; (3f8 <static_lib_init+0x3f8>)
14: 58e3 ldr r3, [r4, r3]
16: 461a mov r2, r3
18: 2301 movs r3, #1
1a: f8c2 30d0 str.w r3, [r2, #208] ; 0xd0
r2
应该包含 g_appconfig
的起始地址(#208 是我想要在真实世界代码中访问的元素的偏移量),但是在调试时包含 0xff7f4342.
知道这是怎么发生的吗?链接器不应该在链接时替换生成的静态库中 g_appconfig 的地址吗?
如果我自己无法测试,我无法给你一个肯定的答案,但我猜问题是你正在用 -fPIC
构建你的库,但你的主要应用不是。
请记住,当您要求编译器生成与位置无关的代码时,您也在要求它生成与位置无关的数据。在您的情况下,全局变量 g_appconfig
将位于链接器确定的固定位置。
尝试删除库构建中的 -fPIC
选项。由于您只是静态链接,所以您并不真正需要它,而且它更有可能损害您的性能而不是帮助。