当前位置 : 主页 > 编程语言 > c++ >

堆栈指针指向保留的内存

来源:互联网 收集:自由互联 发布时间:2021-06-23
我正在调试英飞凌Tricore TC275上的加密实现代码( reference汇编语言). PMI_PSPR (wx!p): org = 0xC0000000, len = 24K /*Scratch-Pad RAM (PSPR)*/ DMI_DSPR (w!xp): org = 0xD0000000, len = 112K /*Local Data RAM (DSPR)*/ 在调用
我正在调试英飞凌Tricore TC275上的加密实现代码( reference汇编语言).

PMI_PSPR (wx!p): org = 0xC0000000, len = 24K  /*Scratch-Pad RAM (PSPR)*/ 
DMI_DSPR (w!xp): org = 0xD0000000, len = 112K  /*Local Data RAM (DSPR)*/

在调用mac函数后,堆栈指针a [10]始终指向保留的存储区域.

###### typedefs ######
typedef uint16_t limb_t;
typedef limb_t gf_t[DIGITS]; //DIGITS=312
typedef int32_t dslimb_t;
################################

/**Multiply and accumulate c += a*b*/
void mac(gf_t c, const gf_t a, const gf_t b)
1: 0xC0000812:   D9 AA 40 9F   LEA     a10,[a10]-0x9C0 //Load eff. addr.
       /*Reference non-Karatsuba MAC */
       dslimb_t accum[2*DIGITS] = {0};
2: 0xC0000816:   40 A2         MOV.AA  a2,a10
3: 0xC0000818:   D2 02         MOV     e2,0x0 //move 0x0 to d2 and d3
4: 0xC000081A:   C5 03 37 40   LEA     a3,0x137 // 0.5*length of accum
5: 0xC000081E:   89 22 48 01   ST.D    [a2+]0x8,e2 //<= fails here
6: 0xC0000822:   FC 3E         LOOP    a3,0xC000081E 
7: 0xC0000824:   40 AF         MOV.AA  a15,a10

###contents of relevant registers###
                 before        after
1: a[10]         D000 0600     CFFF FC40 (not definend in memory map?)
2: a[2]          D000 0A06     CFFF FC40
3: d[2]          0000 0002     0000 0000
3: d[3]          0000 0000     0000 0000 (would have been set to zero too)
4: a[3]          0000 0186     0000 0137 (#of iterations in loop)
5: a[2]          CFFF FC40     (store failed here)
value@CFFF FC40  ???? ????     ???? ???? (write is not allowed I guess)

0x9C0 = 2496(base10),数组accum的长度为624,每个元素包含一个int32_t.这样分配624 * 4 = 2496字节还是什么?

但是在内存中的这个地址,只要我理解为链接器提供的内存映射,就不允许写入…但生成的汇编代码试图在第5行中执行?

有谁知道我在这里做错了什么?我也尝试使用calloc在堆上分配内存(而不是像上面代码那样的堆栈吗?)但程序仍然崩溃.

我还将dslimb_t accum [2 * DIGITS] = {0}行复制到执行它的程序的开头而没有错误.

非常感谢您的帮助!

编辑

像这样调用mac,统一采样一些统一的随机数

gf_t sk_expanded[DIM],b,c;
for (unsigned i=0; i<DIM; i++) {
    noise(sk_expanded[i],ctx,i);
}
for (unsigned i=0; i<DIM; i++) {
    noise(c,ctx,i+DIM); //noisy elements in c after call
    for (unsigned j=0; j<DIM; j++) {
        uniform(b,pk,i+DIM*j); //uniform random numbers in b after call
        mac(c,b,sk_expanded[j]); //fails here on first call
    }
    contract(&pk[MATRIX_SEED_BYTES+i*GF_BYTES], c);
}

这段代码在我的主机上运行,​​但是在我的tricore微控制器上,它在第一次mac()函数调用中失败了.

由于“堆栈指针”a10之前是0xD0000600,并且堆栈在该平台上向下增长,并且分配给该区域的存储器芯片从0xD0000000 =>开始.你只有0x600字节的堆栈内存可用于本地和其他函数调用(及其本地人!).

Does anybody know what I might be doing wrong here?

但是你试图分配0x9C0字节(对于b和c加上更多的字节,除非那些在寄存器中结束,并且优化器足够智能,不为它们分配堆栈空间),这导致超出设计的内存区域,并且第一次写入指令然后会崩溃.实际上,如果你要求更多的字节,你可能会意外地从Scratch-pad RAM内部开始(结果地址非常接近0xC0000000),然后代码将在清除数组时崩溃,一旦它离开暂存区域.

But the generated assembly code tries to do in line 5?

生成的代码不检查C中的内存可用性,与此类问题有关C是“不安全”的编程语言,程序员维护者/运算符负责构建代码并在堆栈具有的环境中运行它足够的空间.或者将检查添加到动态的代码中,以至于无法在开发期间评估堆栈使用情况,并且代码应该优雅地处理满堆栈情况.

I also tried to use calloc to allocate memory on the heap (instead of the stack like the code above does right?) but the programm still crashed.

看起来像是不同的问题,或者你也有完整的堆(来自评论“堆应该是4k” – 听起来像非常小的堆,也许你已经用其他动态分配已经用尽了,也碎片可能会阻止你的内存分配器返回连续有效的3k阻止您的阵列).堆分配器在其池耗尽时往往会返回NULL,但可能您的平台非常有限,内存分配器在实现中缺少这样的安全代码,以使其更小.

I also copied the line dslimb_t accum[2*DIGITS] = {0} to the start of the program where it was executed without an error.

然后它是全局变量,它被放入类似.data的段中,该段被放置在足够大的内存区域中.

是的,624 32位整数需要至少2496(624 * 4)字节的内存(在C语言中,你通常支付零价格进行抽象,所以在这种情况下任何一块2496字节长的内存,根据你的平台要求对齐,这足以使这成为可能,在像Java这样的其他语言中,这种阵列的总成本要高得多,因为还有GC管理和阵列管理数据,所以你可以在这样的平台上计算大约3000-3500字节).

通常当一个人在如此多的约束系统上发展时(要求本地人的3k堆栈空间声音在桌面/网络编程世界中完全可以忽略不计,但在小型嵌入式系统或旧的8/16位计算机上可能是大量的内存),它可能有助于以“数据驱动”的方式设计代码和算法,即你完全规划你的内存使用,包括代码所在的位置(以及它有多大),本地/全局变量所在的位置,以及请注意,运行代码的所有状态所需的最大堆栈是多少.

您可以首先检查堆栈为何如此低 – “本地数据RAM”似乎大约110k,所以也许你有足够的空间,并且在构建期间有一些选项可以调整堆栈大小(或者链接器脚本可以被调整).

实际上你应该检查你的整个内存消耗设计,即你真正需要在内存中的数据,它在哪里,哪些是临时的,它们的生命周期等等(至少在粗略的千字节估计),并检查对芯片上的物理可用内存,因此您可以了解编写代码的粗心大意,或者最终是否已经为您的特定任务内存不足,甚至在开始实施之前. (您可以首先检查链接器映射文件,查看生成了多少代码,以及.data / .bss / .rodata / etc部分中的固定变量有多大,然后检查所有局部变量和堆分配)

然后可能在某种结构中分配所需的内存.你甚至需要动态分配吗?难道你不能简单地在代码中设计整个.data段作为少数全局结构变量,通过它们所属的抽象对各种数据进行分组,并在其他代码中使用这些全局变量而不进行任何动态分配?

此外,如果您正在编写某种类型的库/支持功能,请确保不要耗尽平台的所有资源,否则不清楚如何将您的功能与实际任务结合使用.

网友评论