【发布时间】:2022-01-07 00:09:31
【问题描述】:
我需要帮助将我的嵌入式 C++ 代码(在 ARM 处理器上运行)移植到本地机器 (x86)。
代码的某些部分在专用内存部分 (ROM) 上运行,以节省一些嵌入式 RAM。这是通过编译器特性attribute((section))实现的。
使用 clang/clang++ v.12 无法在我的本地 PC (Win32) 上构建相同的代码。我遇到了几个“节类型冲突”编译错误。
我有一个简短的示例代码可以重现该问题:
Constant.hpp
#pragma once
class Constant {
public:
Constant(int val) { value = val; }
int get() { return value; }
private:
int value = 0;
};
Global.hpp
#pragma once
#include "Constant.hpp"
static Constant myConstant = Constant{3};
extern Constant * const pConstant __attribute__((__section__(".mySection1"))) = &myConstant;
Sum.hpp
#pragma once
struct Sum {
Sum() = default;
int calculate(int a, int b) __attribute__((__section__(".mySection1")));
};
main.cpp
#include <iostream>
#include "Global.hpp"
#include "Sum.hpp"
extern Constant * const pConstant;
int main(int argc, char **argv) {
Sum * sum = new Sum();
int result = sum->calculate(1, pConstant->get());
std::cout << result << std::endl;
return 0;
}
编译器输出为:
error: 'calculate' causes a section type conflict with 'pConstant'
int calculate(int a, int b) __attribute__((__section__(".mySection1")));
^
.../Global.hpp:6:25: note: declared here
extern Constant * const pConstant __attribute__((__section__(".mySection1"))) = &myConstant;
如果我使用 2 个不同的部分(.mySection1 用于变量,mySection2 用于方法),代码将成功构建并运行。反汇编代码如下:
.../Sum.cpp.obj: file format pe-i386
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x2a nreloc 3 nlnno 0 checksum 0x7187c290 assoc 1 comdat 0
[ 2](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0 checksum 0x0 assoc 2 comdat 0
[ 4](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x4 nreloc 0 nlnno 0 checksum 0x0 assoc 3 comdat 0
[ 6](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x1f nreloc 0 nlnno 0 checksum 0x6ff4fbec assoc 4 comdat 2
[ 8](sec 4)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 ??0Constant@@QAE@H@Z
[ 9](sec 5)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .mySection2
AUX scnlen 0x2b nreloc 2 nlnno 0 checksum 0x56c90986 assoc 5 comdat 0
[ 11](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x11 nreloc 0 nlnno 0 checksum 0x80cdff44 assoc 6 comdat 2
[ 13](sec 6)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 ?get@Constant@@QAEHXZ
[ 14](sec 7)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .mySection1
AUX scnlen 0x4 nreloc 1 nlnno 0 checksum 0x0 assoc 7 comdat 0
[ 16](sec 8)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .CRT$XCU
AUX scnlen 0x4 nreloc 1 nlnno 0 checksum 0x0 assoc 8 comdat 0
[ 18](sec 9)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .drectve
AUX scnlen 0x18 nreloc 0 nlnno 0 checksum 0x63557b96 assoc 9 comdat 0
[ 20](sec 10)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .debug$S
AUX scnlen 0x56c nreloc 23 nlnno 0 checksum 0xa675e8b1 assoc 10 comdat 0
[ 22](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .debug$S
AUX scnlen 0x150 nreloc 9 nlnno 0 checksum 0xecc1ccc6 assoc 4 comdat 5
[ 24](sec 14)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .debug$S
AUX scnlen 0x11c nreloc 7 nlnno 0 checksum 0xefad5adf assoc 6 comdat 5
[ 26](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .debug$T
AUX scnlen 0x3b0 nreloc 0 nlnno 0 checksum 0x954cd43c assoc 11 comdat 0
[ 28](sec 12)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .llvm_addrsig
AUX scnlen 0x4 nreloc 0 nlnno 0 checksum 0x9c7eb272 assoc 12 comdat 0
[ 30](sec -1)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000001 @feat.00
[ 31](sec 1)(fl 0x00)(ty 20)(scl 3) (nx 0) 0x00000000 ??__EmyConstant@@YAXXZ
[ 32](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x00000000 _myConstant
[ 33](sec 5)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 ?calculate@Sum@@QAEHH@Z
[ 34](sec 1)(fl 0x00)(ty 20)(scl 3) (nx 0) 0x00000020 __GLOBAL__sub_I_Sum.cpp
[ 35](sec 7)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 ?pConstant@@3QAVConstant@@A
[ 36](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 Sum.cpp
File
我的印象是 x86 的 clang 不允许将常量变量和函数放在同一节中,但我在 clang 编译器参考中找不到任何 x86/Win32 限制...
有什么想法吗?
【问题讨论】:
-
也许这和内存保护有关? (例如,该部分是否设置了
IMAGE_SCN_MEM_EXECUTE位)。您是否尝试过仔细查看可执行文件的 PE 标头?