请看下面的代码:
#include <stdio.h> int gprs[32]; int main(void) { printf("%p\n", (void*)&gprs); }
使用-pie(似乎是默认值)编译会产生:
-pie
0x55c183951040
当使用-no-pie编译时,将生成:
-no-pie
0x404060
有人能解释一下-pie是如何影响文件作用域变量的地址的吗?注意:默认情况下,Clang似乎有-no-pie。
ux6nzvsh1#
有人能解释一下-pie是如何影响文件作用域变量的地址的吗?使用-pie,操作系统可以将可执行文件加载到内存中的任何地址。在Windows下,这是使用“基址重定位表”来完成的;在Linux下,这是使用“位置无关代码”来完成的。在这种情况下,出于安全原因,许多现代操作系统将可执行文件加载到内存中的任何(随机)地址(因为如果变量gprs的地址未知,则更难编写访问该变量的病毒)。这意味着以下示例中(static或全局)变量a和b的地址之差:
gprs
static
a
b
printf("%p, %p\n", &a, &b);
...应为常量,但每次运行程序时a(和b)的地址可能不同。使用-no-pie,在两种操作系统下都生成“位置相关代码”,在Windows下不生成“基址重定位表”。这意味着可执行文件只能被加载到一个固定的内存地址中,因此,static或全局变量(但不一定是非static本地变量)的地址在多次运行程序时不应该改变。
1条答案
按热度按时间ux6nzvsh1#
有人能解释一下
-pie
是如何影响文件作用域变量的地址的吗?使用
-pie
,操作系统可以将可执行文件加载到内存中的任何地址。在Windows下,这是使用“基址重定位表”来完成的;在Linux下,这是使用“位置无关代码”来完成的。在这种情况下,出于安全原因,许多现代操作系统将可执行文件加载到内存中的任何(随机)地址(因为如果变量
gprs
的地址未知,则更难编写访问该变量的病毒)。这意味着以下示例中(
static
或全局)变量a
和b
的地址之差:...应为常量,但每次运行程序时
a
(和b
)的地址可能不同。使用
-no-pie
,在两种操作系统下都生成“位置相关代码”,在Windows下不生成“基址重定位表”。这意味着可执行文件只能被加载到一个固定的内存地址中,因此,
static
或全局变量(但不一定是非static
本地变量)的地址在多次运行程序时不应该改变。