设置对象section的另一种方法是使用 pragma section。 通过使用编译指示section,可以通过为整组对象设置编译指示section,轻松地将多个对象定位到用户定义的section中。 该组必须包含在 pragma section 指令中才能正确设置该section和该section的属性:
#pragma section "<name>" [<flags>] [<alignment>]
<objects>
#pragma section
a allocatable. 可定位的,该项总是置位This is always set
B uninitialized 未初始化的
w writable 可写的
x executable 可执行的
s using small addressing 使用小地址
z using absolute addressing 使用绝对寻址
默认对齐方式<alignment>取决于定义的数据,而默认标志<flags>是 a 和 w。
要在 pragma section 指令定义的section中分配代码,必须设置 x 标志<flags>。
可执行意味着只有代码将位于此section中,而编译指示section中的所有数据将位于默认数据section中。 没有 x 标志的编译指示section用于分配数据。
如果要将数据放入小的或绝对可寻址的内存区域,对于小型可寻址内存区域使用 .sdata 或者 . sbss 开头,绝对可寻址的内存区域以.zdata. 或 . zbss开头 。 这是告诉链接器将数据放入适当的内存区域的唯一方法。
【注意】代码和数据编译指示可以嵌套。
例子
在这两个示例中,#pragma section“.text”中的所有代码都将放在 .text section中。 命令#pragma section ".data.mysection" 将所有全局未/初始化的数据放在.data.mysection的section中。
例1
#pragma section ".text" ax
#pragma section ".data.mysection" aw
int foo data;
#pragma section
int
foo(void)
{
int i;
...
return (foo data + i);
}
#pragma section
Example 2
#pragma section ".data.mysection" aw
#pragma section ".text" ax
int foo data;
int
foo(void)
{
int i;
...
return (foo data + i);
}
#pragma section
#pragma section
限制
在 1 字节section对齐的section中,整数可能位于奇数地址。 这将导致程序出现故障,因为编译器使用 st .w 和 ld .w 指令来访问整数。 但是 st .w 和 ld .w 指令仅对访问 16 位对齐的内存位置有效。
示例 3
如果您使用也在中断中访问的全局变量,则这些变量的原子加载修改和存储将是必不可少的。 为了解决这个问题,用户应该在一个 4 字节section对齐的绝对可寻址区域中定义这些变量。 在以下示例中,位域 Bits 是通过 #pragma section“.zdata”分配的。 对应于 TriCore EABI,位域的对齐取决于其大小。 如果大小为 4 字节section,则位域的对齐方式为 4 字section。
volatile struct {
unsigned int bit0 :1;
unsigned int bit1 :1;
unsigned int bit2 :1;
unsigned int field :3;
unsigned int dummy :16;
} T Bits;
#pragma section ".zdata" awz
T_Bits Bits;
#pragma section
选项 -funsigned-bitfields 是根据 TriCore EABI 规范默认设置的。
例子
以下示例显示如何使用 pragma section定义变量的section。
1.整型变量 a 位于名为.sdata. relative 的 2 字section对齐section中。 此section是可分配的 (a)、可写的 (w) 和可小寻址的 (s):
请注意该section名称中的前导点。
#pragma section ".sdata.relative" aws 2 //opening pragma section
int a;
#pragma section //closing pragma section
2.在下例中,编译指示section用于定位用户定义section .fastram 中的函数 int foo (void)。
#pragma section ".fastram" ax
int foo (void);
#pragma section
3.在下例子,函数 int foo (void) 和 int bar(void) 位于 .code section。 由于此 pragma section设置了 x 标志,因此除函数外的所有对象都将忽略它。所以变量 a 被定位为common symbol 。
#pragma section ".fastram" ax
int a;
int foo (void);
int bar (void);
#pragma section
4.在此示例中,函数声明包含在没有设置 x 标志的编译指示section中。
此 pragma section仅对变量有效。 变量 a 和 b 位于 .sdata.relative 段中。 函数 int foo(void) 的编译指示section被忽略,该函数位于默认段. text 。
#pragma section ".sdata.relative" aws
int a;
int b;
int foo (void);
#pragma section
5.编译器支持静态变量的编译指示
#pragma section ".sdata.foo" aws
static unsigned short s1;
#pragma section
输入section .sdata.foo 将由默认链接描述文件定位在输出section .sdata 中。
要获取有关 s1 的符号信息,请使用以下命令之一“. tricore-objdump” 显示起始地址、输出section、大小和符号名称。
tricore-objdump --syms test.o | grep s1
tricore-nm -f sysv test.o | grep s1
条目 d 将变量 s1 标记为静态变量。 全局符号用 D 标记。
【注意】静态变量不会显示在链接器的 Mapfile 中。
-Wno-deprecated-pragma-section-name, -Wdeprecated-pragma-section-name
选型 -Wdeprecated-pragma-section-name默认是置位的,如果section name没有被引号括起来,它会发出警告。
选项-Wno-deprecated-pragma-section-name 将允许使用旧语法并迁移遗留代码。
#pragma section .foodata aw
short z = 1;
#pragma section