读书笔记,关于pe file的section及pragma命令

本文介绍了编译器和链接器创建标准节之外,可使用#pragma指令创建自定义节,编译器会将初始化变量存于新节。还阐述了#pragma指令能让编译器提供特定功能且保持与C和C++语言兼容,可用于条件语句等,若编译器不识别会发警告但继续编译。

The following table shows some of the more common section names and explains each section's purpose.

Section NamePurpose
.bssUninitialized data
.CRTRead-only C run-time data
.dataInitialized data
.debugDebugging information
.didataDelay imported names table
.edataExported names table
.idataImported names table
.rdataRead-only run-time data
.relocRelocation table information
.rsrcResources
.text.exe's or DLL's code
.tlsThread-local storage
.xdataException handling table

In addition to the standard sections created by the compiler and the linker, you can create your own sections when you compile using the following directive:

#pragma data_seg("sectionname")

So, for example, I can create a section called "Shared" that contains a single LONG value, as follows:

#pragma data_seg("Shared")
LONG g_lInstanceCount = 0;
#pragma data_seg()

When the compiler compiles this code, it creates a new section called Shared and places all the initialized data variables that it sees after the pragma in this new section. In the example above, the variable is placed in the Shared section. Following the variable, the #pragma dataseg() line tells the compiler to stop putting initialized variables in the Shared section and to start putting them back in the default data section. It is extremely important to remember that the compiler will store only initialized variables in the new section. For example, if I had removed the initialization from the previous code fragment (as shown in the following code), the compiler would have put this variable in a section other than the Shared section:

#pragma data_seg("Shared")
LONG g_lInstanceCount;
#pragma data_seg()

The Microsoft Visual C++ 6.0 compiler offers an allocate declaration specifier, however, that does allow you to place uninitialized data in any section you desire. Take a look at the following code:

***************************************************************************
// Create Shared section & have compiler place initialized data in it.
#pragma data_seg("Shared")

// Initialized, in Shared section
int a = 0; 

// Uninitialized, not in Shared section
int b; 

// Have compiler stop placing initialized data in Shared section.
#pragma data_seg()

// Initialized, in Shared section
_ _declspec(allocate("Shared")) int c = 0; 

// Uninitialized, in Shared section 
_ _declspec(allocate("Shared")) int d; 

// Initialized, not in Shared section
int e = 0; 

// Uninitialized, not in Shared section
int f;  

************************************************************************************************************

--摘自<programming application for Microsoft Windows>

#pragma directives -- 摘自msdn library

Each implementation of C and C++ supports some features unique to its host machine or operating system. Some programs, for instance, need to exercise precise control over the memory areas where data is placed or to control the way certain functions receive parameters. The #pragma directives offer a way for each compiler to offer machine- and operating system-specific features while retaining overall compatibility with the C and C++ languages. Pragmas are machine- or operating system-specific by definition, and are usually different for every compiler.

Pragmas can be used in conditional statements, to provide new preprocessor functionality, or to provide implementation-defined information to the compiler. The Microsoft C and C++ compilers recognize the following pragmas:

1. Supported only by the C++ compiler.

#pragma token-string

The token-string is a series of characters that gives a specific compiler instruction and arguments, if any. The number sign (#) must be the first non-white-space character on the line containing the pragma; white-space characters can separate the number sign and the word pragma. Following #pragma, write any text that the translator can parse as preprocessing tokens. The argument to #pragma is subject to macro expansion.

If the compiler finds a pragma it does not recognize, it issues a warning, but compilation continues.

Some pragmas provide the same functionality as compiler options. When a pragma is encountered in source code, it overrides the behavior specified by the compiler option. For example, if you specified tabindex="0" keywords="_core_.2f.Zp">/Zp8, you can override this compiler setting for specific portions of the code with pack:

cl /Zp8 ...

<file> - packing is 8
// ...
#pragma pack(push, 1) - packing is now 1
// ...
#pragma pack(pop) - packing is 8
</file>
在 ARM 架构下,若需替代 `#pragma section` 编译指令以实现对变量或代码段的自定义布局,可以使用 GCC 或 ARM 编译器支持的 `__attribute__` 语法。该方法在嵌入式开发中被广泛采用,尤其适用于需要将变量或函数放置在特定内存区域(如 Flash 或 RAM)的场景。 ### 使用 `__attribute__((section("段名")))` 替代 `#pragma section` GCC 和 ARM 编译器支持使用 `__attribute__((section("section-name")))` 将变量或函数放置到指定段中,这种方式在 ARM 架构中是标准做法。例如: ```c const uint32_t firmwareVersion __attribute__((section("MY_FLASH_SECTION"))) = 0x01020304; ``` 该语句将变量 `firmwareVersion` 放置在名为 `MY_FLASH_SECTION` 的段中,适用于需要固化数据或保留特定变量的应用场景。 ### 配置链接器脚本以定义段地址 为了确保该段在最终映像中被正确放置,需要在链接器脚本(如 `.ld` 文件)中定义该段的起始地址和大小。例如: ```ld MEMORY { FLASH (rx) : ORIGIN = 0x080C0000, LENGTH = 512K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K } SECTIONS { . = ORIGIN(FLASH) + LENGTH(FLASH) - 0x1000; .my_flash_section : { *(.MY_FLASH_SECTION) } > FLASH } ``` 上述配置将 `.MY_FLASH_SECTION` 段放置在 Flash 末尾预留的区域中,确保其不会与代码或默认数据段发生冲突。 ### 使用 `__attribute__((used))` 避免被优化 为了防止编译器因变量未被显式引用而将其优化掉,可以结合 `__attribute__((used))` 使用: ```c const uint32_t calibrationData __attribute__((section("MY_FLASH_SECTION"), used)) = 0xAABBCCDD; ``` 该方式确保变量即使未在代码中显式使用,也会保留在目标段中。 ### 在 IAR 编译器中实现类似功能 对于 IAR 编译器,虽然不支持 `__attribute__`,但可以通过 `.icf` 链接器配置文件定义段,并结合 `#pragma location` 实现类似功能: ```icf define symbol MY_FLASH_SECTION = 0x080C0000; define symbol MY_FLASH_SECTION_SIZE = 0x1000; place at address mem: MY_FLASH_SECTION { readonly section MY_FLASH_SECTION }; ``` 然后在代码中: ```c #pragma location = "MY_FLASH_SECTION" const uint32_t firmwareVersion = 0x01020304; ``` 该方式在 ARM 架构下可有效替代 `#pragma section`,并确保变量被正确放置[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值