求大神解答:如何判断linux 可执行文件是否为PIE(地址无关可执行文件)?

王的璋 2014-11-18 10:10:16
最近阅读程序员自我修养这本书,遇到一个问题,百思不得其解

上代码,很简短:
PLT.c

#include <stdio.h>
int global_variable1 = 0;
void foo(){
global_variable1 = 1;
printf("global_variable:%d",global_variable1);
}

编译PIC共享文件 PLT.so:gcc -fPIC -shared -o PLT.so PLT.c
program.c

extern int global_variable1;
void main(){
global_variable1 = 1;
// foo();
// return 1;
}


编译 可执行文件 program: gcc -o program program.c ./PLT.so
program中global_variable1位于bss段,赋值为1执行movl $ox1 bss_address
倘若我使用 -fPIE参数:gcc -fPIE -o program program.c ./PLT.so
发现global_variable变量需要重定位,重定位地址位于GOT中。

那么问题来了:
1.首先,书上说通过readelf -d program |grep TEXTREL(代码重定位)判断文件是否是地址无关代码文件
我发现无论是否使用-fPIE参数,输出都是空,如此说明二者产生的program都是PIE?
2.PIE是代码部分地址无关的,可执行文件虚拟地址可以确定,linux下起始一般是80040000, gcc -o program program.c ./PLT.so该命令下,既然装载地址固定,那么代码中涉及到的数据地址,都位于bss或者data段,链接时已经确定了地址,
而代码如果涉及到函数调用,通过plt,也是地址无关的,那么是否可以说不通过-fPIE参数,而获得的program可执行文件也同样是PIE呢?如果是,那-fPIE的意义又在哪里呢?
3.什么条件使用和不使用-fPIE参数呢?
附图两张,其中提到可执行文件使用非PIC机制,且装载时代码并不重定位,那岂不是又矛盾了?



初涉及此方面问题,还请大神作答,十分感谢!
...全文
981 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
Cody2k3 2014-11-27
  • 打赏
  • 举报
回复
引用 楼主 qilvmilv 的回复:
最近阅读程序员自我修养这本书,遇到一个问题,百思不得其解 上代码,很简短: PLT.c

#include <stdio.h>
int global_variable1 = 0;
void foo(){
    global_variable1 = 1;
    printf("global_variable:%d",global_variable1);
}
编译PIC共享文件 PLT.so:gcc -fPIC -shared -o PLT.so PLT.c program.c

extern int global_variable1;
void main(){
    global_variable1 = 1;
   // foo();
   // return 1;
}
编译 可执行文件 program: gcc -o program program.c ./PLT.so program中global_variable1位于bss段,赋值为1执行movl $ox1 bss_address 倘若我使用 -fPIE参数:gcc -fPIE -o program program.c ./PLT.so 发现global_variable变量需要重定位,重定位地址位于GOT中。 那么问题来了: 1.首先,书上说通过readelf -d program |grep TEXTREL(代码重定位)判断文件是否是地址无关代码文件 我发现无论是否使用-fPIE参数,输出都是空,如此说明二者产生的program都是PIE? 2.PIE是代码部分地址无关的,可执行文件虚拟地址可以确定,linux下起始一般是80040000, gcc -o program program.c ./PLT.so该命令下,既然装载地址固定,那么代码中涉及到的数据地址,都位于bss或者data段,链接时已经确定了地址, 而代码如果涉及到函数调用,通过plt,也是地址无关的,那么是否可以说不通过-fPIE参数,而获得的program可执行文件也同样是PIE呢?如果是,那-fPIE的意义又在哪里呢? 3.什么条件使用和不使用-fPIE参数呢? 附图两张,其中提到可执行文件使用非PIC机制,且装载时代码并不重定位,那岂不是又矛盾了? 初涉及此方面问题,还请大神作答,十分感谢!
书上说的TEXTREL只是用来判断shared lib的,不是用来判断executable 是否是PIE的 PIE 和非PIE的区别在于是否使用固定的load address, 非PIE的load的地址是固定的,可以在link的时候指定 PIE,load的地址可以不固定,因为PIE本质上是一个shared object,所以和普通的shared lib一样可以load到不同地方 尤其在开启address space layout randomization 的情况下, 会有意load到随机的地址来增强安全性 判断PIE非PIE用elf header里面的 type,如下所示 gcc -o program program.c PLT.so gcc -fPIE -pie -o program_pie program.c PLT.so (注意fPIE只是compile 指令,另需pie传给linker) $readelf -h program|grep Type Type: EXEC (Executable file) $readelf -h program_pie|grep Type Type: DYN (Shared object file) 用size 命令看binary里面的地址, 注意pie的binary是以base 地址0 开始的 $size --format=sysv program program : section size addr .interp 28 4194816 .note.ABI-tag 32 4194844 .hash 68 4194880 .... $size --format=sysv program_pie program_pie : section size addr .interp 28 512 .note.ABI-tag 32 540 .hash 76 576 如果你在你的program.c里面加上一段打印地址的logic 1 #include <stdio.h> 2 extern int global_variable1; 3 int foo = 0; 4 void main(){ 5 global_variable1 = 1; 6 printf("addr=%x\n", &foo); 7 } 非pie的程序总是打印相同的地址, pie的程序的地址是不断变化的 $./program addr=600ae8 $./program addr=600ae8 $./program_pie addr=3e499c74 $./program_pie addr=aaf75c74 $./program_pie addr=d1a1c74 最后一点虽然non pie也使用了许多pic的技术,但是有些地方仍然无法动态重定位所以限制了它实现完全的position independent
王的璋 2014-11-20
  • 打赏
  • 举报
回复
自顶一下,莫非大神们在等双十一收货,无暇顾及

18,784

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 专题技术讨论区
社区管理员
  • 专题技术讨论区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧