x86_64 Linux下如何将非.text的自定义节设置为可执行权限
自定义节丢失可执行权限的核心原因
链接器对输出节的权限赋值遵循节自身属性标记 > MEMORY区域默认属性的优先级规则。你之前遇到的所有权限异常,本质都是自定义节没有显式声明可执行属性,导致链接器按照内置的默认节名规则推断权限:
- 节名匹配内置规则(如
.text默认带可执行、.rodata默认只读、.data默认可读写)时,会自动赋予对应权限 - 节名不匹配内置规则时,哪怕所在MEMORY区域标记了可执行属性,链接器也会默认给节分配只读、无执行的权限,最终导致程序加载时触发非执行页的段错误
正确配置方法
1. 给自定义可执行节显式添加权限标记
在链接脚本的SECTIONS规则中,给自定义节的声明行加上:rx属性标记,这是GNU ld原生支持的语法,可直接强制指定节的读、执行权限:
SECTIONS { . = __linux_mmap_min_addr; # 给自定义的.my_section显式标记可读、可执行权限 .my_section :rx { *(.my_section*) } > rom .rodata :r { *(.rodata*) } > rom }
其中属性标记的含义:
r:节内容可读w:节内容可写x:节内容可执行
2. 解释你之前尝试迁移到.text节失败的原因
GNU ld的内置权限规则仅在你没有自定义该节的装载规则时生效。如果你在链接脚本里重写了.text节的装载逻辑,但没有显式给该节加:rx标记,内置的.text默认可执行规则就会失效——哪怕节名叫.text,最终也会被分配无执行权限。正确写法示例:
# 这种写法会丢失.text的默认可执行权限,和你之前遇到的旧问题一致 .text : { *(.my_section*) } > rom # 正确写法:自定义.text节时也要显式加属性标记 .text :rx { *(.my_section*) } > rom
验证方法
修改完链接脚本后,执行以下命令确认权限正确:
- 用
readelf -S 输出程序名查看节表,确认.my_section的Flags列带有X标记(即标记为R X,而非仅R) - 用
readelf -l 输出程序名查看程序头表,确认包含该节的程序段Flg列带有E(可执行)标记
注意:如果可执行节和只读数据节的加载地址没有按内存页边界对齐,链接器可能会把二者合并到同一个程序段里,此时段权限会以最先定义的节的属性为准,可能导致可执行权限被覆盖。建议在脚本中给可执行节和只读数据节之间加上页对齐规则,比如在节装载规则里加
. = ALIGN(0x1000);确保边界对齐,让链接器生成独立的权限段。
内容的提问来源于stack exchange,提问作者Edward Chamberlain
相关产品推荐
相关产品推荐

