我的问题可能看起来很奇怪
事实上,这是上下文:
我目前在切换时遇到一个奇怪的问题 -关于我正在从事的项目- 核心从pullinino到CV32(也发生了一些其他变化,例如关于crt0,如一些数据内存重置)。
这是一个(真实的)例子,说明了一个非常简单的 main 所发生的情况
(我无法提供startup/crt0文件编辑:我在帖子后面部分给出了它).
#include <string.h>
#include <inttypes.h>
#include <stdio.h>
typedef struct
{
uintptr_t addr;
uint32_t foo;
} some_struct_t;
static uint32_t text_in_data[8] = {0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888};
uint32_t text_in_data2[8] = {0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888};
some_struct_t text_in = {(uintptr_t)text_in_data, 8};
static some_struct_t text_in2 = {(uintptr_t)text_in_data, 8};
int main(void)
{
some_struct_t text_in3 = {(uintptr_t)text_in_data, 8};
static some_struct_t text_in4 = {(uintptr_t)text_in_data, 8};
static some_struct_t text_in5 = {(uintptr_t)text_in_data2, 8};
printf("text_in_data[]: ");
for (uint8_t i=0;i<8;i++)
{
printf("0x%08x, ",(unsigned int)text_in_data[i]);
}
printf("\n");
printf("text_in_data2[]: ");
for (uint8_t i=0;i<8;i++)
{
printf("0x%08x, ",(unsigned int)text_in_data2[i]);
}
printf("\n");
printf("text_in1.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in.addr,(unsigned int)text_in_data);
printf("text_in2.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in2.addr,(unsigned int)text_in_data);
printf("text_in3.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in3.addr,(unsigned int)text_in_data);
printf("text_in4.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in4.addr,(unsigned int)text_in_data);
printf("text_in_data2.addr 0x%08x -- @text_in_data2 0x%08x\n",(unsigned int)text_in5.addr,(unsigned int)text_in_data2);
text_in = (some_struct_t){(uintptr_t)text_in_data, 8};
text_in2 = (some_struct_t){(uintptr_t)text_in_data, 8};
text_in3 = (some_struct_t){(uintptr_t)text_in_data, 8};
text_in4 = (some_struct_t){(uintptr_t)text_in_data, 8};
text_in5 = (some_struct_t){(uintptr_t)text_in_data2, 8};
printf("text_in1.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in.addr,(unsigned int)text_in_data);
printf("text_in2.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in2.addr,(unsigned int)text_in_data);
printf("text_in3.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in3.addr,(unsigned int)text_in_data);
printf("text_in4.addr 0x%08x -- @text_in_data 0x%08x\n",(unsigned int)text_in4.addr,(unsigned int)text_in_data);
printf("text_in_data2.addr 0x%08x -- @text_in_data2 0x%08x\n",(unsigned int)text_in5.addr,(unsigned int)text_in_data2);
return 0;
}
gives
text_in_data[]: 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
text_in_data2[]: 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
text_in1.addr 0x00000000 -- @text_in_data 0x00140478
text_in2.addr 0x00000000 -- @text_in_data 0x00140478
text_in3.addr 0x00140478 -- @text_in_data 0x00140478
text_in4.addr 0x00000000 -- @text_in_data 0x00140478
text_in_data2.addr 0x00000000 -- @text_in_data2 0x00140498
text_in1.addr 0x00140478 -- @text_in_data 0x00140478
text_in2.addr 0x00140478 -- @text_in_data 0x00140478
text_in3.addr 0x00140478 -- @text_in_data 0x00140478
text_in4.addr 0x00140478 -- @text_in_data 0x00140478
text_in_data2.addr 0x00140498 -- @text_in_data2 0x00140498
第一个问题是text_in<x>.addr
当使用静态存储定义时,不会被初始化,但本地定义会被初始化。
有很多事情可以解释这种行为,例如我们正在重置 crt0 中的数据内存。
编辑:重置不是由于数据内存重置造成的,测试固件代码没有发生这种重置,它已通过帖子后面提供的修复程序进行了纠正
但我无法理解的是text_in_data<x>
初始化得很好,但是text_in<x>
is not.
它们应该共享相同的部分(=以相同的方式存储在相同的位置),不是吗?
它们之间的唯一区别是有些是数组,有些是结构......
我查看了原始pulpinino之间的差异crt0.riscv.S https://github.com/sifive/picolibc/blob/master/libgloss/riscv/crt0.S以及我们正在使用的那个。
没有任何差异可以解释这种行为,但我发现了这一点patch https://sourceware.org/pipermail/newlib/2021/018247.html.
确实,最新的crt0.S https://raw.githubusercontent.com/pulp-platform/pulpino/master/sw/ref/crt0.riscv.S包含更多更正
But by JUST更换la a0, _edata
by la a0, _bss_start
, that 使代码片段工作.
但无法真正解释为什么会有这种行为。因为使用edata
在 bss 重置循环中,我想我明白最后一个edata
未对齐的单词也被重置
(. = ALIGN(4);
之间_edata
and _bss_start
)
BUT这并不能解释为什么在结构和数组之间修复之前有如此不同的行为......
这是链接器脚本的一部分
.data : {
. = ALIGN(4);
sdata = .;
_sdata = .;
*(.data);
*(.data.*)
edata = .;
_edata = .;
} > dataram
.bss :
{
. = ALIGN(4);
_bss_start = .;
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
*(COMMON)
_bss_end = .;
} > dataram
/* ensure there is enough room for stack */
.stack (NOLOAD): {
. = ALIGN(4);
. = . + _min_stack ;
. = ALIGN(4);
stack = . ;
_stack = . ;
} > stack
.stab 0 (NOLOAD) :
{
[ .stab ]
}
.stabstr 0 (NOLOAD) :
{
[ .stabstr ]
}
.bss :
{
. = ALIGN(4);
_end = .;
} > dataram
做了之后riscv32-corev-elf-objdump -d *.elf
,两个报告之间的唯一区别是 bss 重置循环的开始地址。
但地址变为0x1405bc
(用于工作),以及0x14059c
(对于不工作的人)。
0x14059c
是地址text_in
对于那些二进制文件。
您是否可以解释为什么数组和结构之间存在这种差异以及为什么此补丁纠正了该问题?