全局变量反汇编与重定位
目录
- 全局变量反汇编与重定位
- 引入
- nopie分析
- MAP
- 普通变量
- 指针变量
- print函数
- pie分析
- MAP
- 汇编方式
- 地址分析
- uboot的pie
- 小结重定位数据段
*(adr+offset)=*(adr+offset)+offset
- 参考文章
title: 全局变量反汇编与重定位
date: 2019/02/23 21:10:08
toc: true
---
全局变量反汇编与重定位
引入
本文完整代码地址 https://gitee.com/layty/Jz2440/tree/master/Assembler/02-global_test
思考这样一个问题,全局变量是怎么存储的,怎么使用的,反汇编后是什么样子的?
最理想的取地址应该是这样的,但是并没有这样的指令,操作数不可能是一个32位的数
ldr r0,[a的地址]
所以我们还想这样,还需要 将 r1 赋值32位的地址..所以单纯的赋值没有办法实现这个操作
ldr r0,[r1]
也就是需要这么做
ldr r0,[pc,offset] ;lable1lable1: addr_vallabel2_addr_val: val
我们写这样一段代码测试一下.
#include <stdio.h>
int a=0;
int b=1;int test(int c)
{c=c+1;printf("hello %d",c);return c;
}
typedef int (*funpt)(int);
funpt pt =&test;int main()
{a=3;b=b+1;test(a);pt(b);
}
makefiel如下,反汇编中加入c语言信息,加入-S
选项,cc
中加入-g
选项
all:arm-linux-gcc -g -o o.out globl_var.c -Wl,-Map=gcc.maparm-linux-objdump -D -S o.out>o.dis
claen:rm *.out
nopie分析
一般我们编译的时候都是nopie,pie我是在编译uboot时候了解到的,本篇文章也是关于uboot重定位分析的子章节
MAP
我们先来看下map文件的地址,有助于后续的分析
.text 0x00008380 test
.bss 0x000105f8 a
.data 0x000105f0 pt0x000105ec b
普通变量
从main
函数入手,先从[pc, #88]
的地方取得一个值,再从这个值所表示的地址中取值
a=3;83cc: e59f2050 ldr r2, [pc, #80] ; 8424 <main+0x64>83d0: e3a03003 mov r3, #3 ; 0x383d4: e5823000 str r3, [r2]8424: 000105f8 .word 0x000105f88428: 000105ec .word 0x000105ec842c: 000105f0 .word 0x000105f0 000105ec <b>:105ec: 00000001 .word 0x00000001000105f0 <pt>:105f0: 00008380 .word 0x00008380
Disassembly of section .bss:000105f4 <completed.5877>:105f4: 00000000 .word 0x00000000000105f8 <a>:105f8: 00000000 .word 0x00000000
从代码上可以看出来8424
这个地方存储的就是变量的地址,也就是这么一个示意图
可以看到a所表示的地址的值,确实是0,实际上这个是存在bss段的.
接着来看代码b=b+1
,多了一个取值的步骤
b=b+1;83d8: e59f3048 ldr r3, [pc, #72] ; 8428 <main+0x68>83dc: e5933000 ldr r3, [r3]83e0: e2832001 add r2, r3, #1 ; 0x183e4: e59f303c ldr r3, [pc, #60] ; 8428 <main+0x68>83e8: e5832000 str r2, [r3]8424: 000105f8 .word 0x000105f88428: 000105ec .word 0x000105ec842c: 000105f0 .word 0x000105f0 000105ec <b>:105ec: 00000001 .word 0x00000001
指针变量
接着来看下函数指针pt
的处理
pt(b);; 取出指针的地址,这个和我们普通变量操作中先取出变量的地址是一样的83fc: e59f3028 ldr r3, [pc, #40] ; 842c <main+0x6c>; 获取变量的值,也就是指针的值,这里就是test的地址值了; 可以看到 [000105f0]=00008380 确实是 00008380 <test>:8400: e5932000 ldr r2, [r3];取出变量b的地址 然后取出b的值8404: e59f301c ldr r3, [pc, #28] ; 8428 <main+0x68>8408: e5933000 ldr r3, [r3]; 传递为第一个参数840c: e1a00003 mov r0, r38410: e1a0e00f mov lr, pc;r2在上面赋值就是test的值8414: e12fff12 bx r2842c: 000105f0 .word 0x000105f0000105f0 <pt>:105f0: 00008380 .word 0x0000838000008380 <test>:
print函数
在函数中调用了库函数,这里也是使用了相对跳转了
printf("hello %d",c);
839c: e59f0018 ldr r0, [pc, #24] ; 83bc <test+0x3c>
83a0: e51b1008 ldr r1, [fp, #-8]
83a4: ebffffc5 bl 82c0 <_init+0x48>
pie分析
接下去的分析都是针对重定位uboot的,与一般的程序没有关系了,不属于全局变量反汇编的分析
MAP
.text 0x00008380 test
.bss 0x000105f8 a
.data 0x000105f0 pt0x000105ec b
// 上面是nopie 下面是pie的
.text 0x000005f8 test
.data 0x0000887c pt
.data 0x00008878 b
.bss 0x00008884 a
汇编方式
加入pie选项和其实发现,单纯的这段main
和test
代码是一致的
地址分析
69c: 00008884 .word 0x00008884 ;存放的a的地址的lable6a0: 00008878 .word 0x00008878 ;存放的b的地址的lable6a4: 0000887c .word 0x0000887c ;存放的pt的地址的lable
搜索这几个地址值69c
,6a0
,6a4
00000400 <.rel.dyn>:;a420: 0000069c muleq r0, ip, r6424: 00000017 andeq r0, r0, r7, lsl r0;b428: 000006a0 andeq r0, r0, r0, lsr #1342c: 00000017 andeq r0, r0, r7, lsl r0;pt430: 000006a4 andeq r0, r0, r4, lsr #13434: 00000017 andeq r0, r0, r7, lsl r0450: 0000887c andeq r8, r0, ip, ror r8454: 00000017 andeq r0, r0, r7, lsl r0
同时,还有一个关键的东西,就是指针的值是个地址的时候,他的值也会出现在这个表里面
450: 0000887c andeq r8, r0, ip, ror r8454: 00000017 andeq r0, r0, r7, lsl r0
这是什么意思呢
当指针的值是个地址的时候,当重定位之后,这个地址应该同样加上偏移.
uboot的pie
.bss 0x000ae4e0 0x4 board/samsung/smdk2410/libsmdk2410.o0x000ae4e0 a.text 0x000560dc 0x240 board/samsung/smdk2410/libsmdk2410.o0x00056278 main20x00056258 test
.data 0x0006adfc 0x8 board/samsung/smdk2410/libsmdk2410.o0x0006adfc b0x0006ae00 pt
变量分析
00056278 <main2>:56278: e92d4010 push {r4, lr};取出b的地址5627c: e59f402c ldr r4, [pc, #44] ; 562b0 <main2+0x38>;r4=0006adfc是b的地址;取出a的地址56280: e59f302c ldr r3, [pc, #44] ; 562b4 <main2+0x3c>56284: e5942000 ldr r2, [r4]56288: e3a01003 mov r1, #3 ; 0x35628c: e2822001 add r2, r2, #1 ; 0x156290: e1a00001 mov r0, r156294: e5831000 str r1, [r3]56298: e5842000 str r2, [r4]5629c: ebffffed bl 56258 <test>; pt(b)562a0: e5940000 ldr r0, [r4]562a4: e1a0e00f mov lr, pc;到这里为止,r4依然是b的地址,也就是说 pt的地址就是b后面,pt的寻址都是按照b来的;手动计算一下 r4+4=6ae00 这确实是pt的实际地址; 0006ae00 <pt>:; 6ae00: 00056258 .word 0x00056258562a8: e594f004 ldr pc, [r4, #4]562ac: e8bd8010 pop {r4, pc}
我们来看下具体的地址信息
;---------------------------------------------------------------------- 562b0: 0006adfc .word 0x0006adfc ;这个存的是b的地址562b4: 000ae4e0 .word 0x000ae4e0 ;这个存的是a的地址; 这里没有lable存储着pt的地址,程序依靠先找到b的地址,b地址下一个偏移就是pt的地址; pt里面的值也是个地址0006ae00 <pt>:6ae00: 00056258 .word 0x00056258
接下来的就是应该重定位的变量信息,也就是lable和地址,可以看到lable和指针都出现了这张表里面
;存放b的lable的地址71854: 000562b0 .word 0x000562b071858: 00000017 .word 0x00000017;存放a的lable的地址7185c: 000562b4 .word 0x000562b471860: 00000017 .word 0x00000017;这里没有存放pt的lable地址 ,依靠b的地址来寻找;pt的值也是个地址值,那么这个地址也应该处理72c1c: 0006ae00 .word 0x0006ae0072c20: 00000017 .word 0x00000017
小结重定位数据段
也就是说,这个特殊的段<.rel.dyn>
应该存放有所有值是地址的单元的地址.
反汇编文件可以看成数据段加指令段,这里考虑数据段
0000: ....
....
xxxx: val 当val表示的是一个地址的时候,现在有两种情况
也就是说包含了
- lable 的地址,存放的是全局变量的地址
- 指针的地址,这个指针存放的是个地址
有了上面的<.rel.dyn>
段重定位数据段就很方便了,将里面的地址挑出来,对其值和其存放的地址都加上偏移即可
- 取出a的地址,此时a的地址应该加上offset
- a的地址怎么取的,也是从一个lable中取的,这个lable也是经过offset的了
- 当a的值是个地址,比如是个函数指针,这个函数指针的值也应该加上offset,才是新定位的函数地址
总结起来一句话
*(adr+offset)=*(adr+offset)+offset
参考文章
uboot的relocation原理详细分析
转载于:https://www.cnblogs.com/zongzi10010/p/10424426.html
全局变量反汇编与重定位相关推荐
- linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...
/// 不需要牛刀,不需要阅读源码,如果只是为解决109的含义.楼主执行的查询命令readelf -S test2.o [ 8] .symtab SYMTAB ...
- uboot2012(一)分析重定位
目录 引入 环境配置 编译体验 入口查找 代码分析 board_init_f pie 内存分布分析 SP设置 board_init_f 重定位 代码段重定位实现 变量地址修改 参考 引入 关于移植,搜 ...
- Windows PE第6章 栈与重定位表
第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...
- 第013课_代码重定位
第013课_代码重定位 第013课 代码重定位 1. 段的概念_重定位的引入 2. 链接脚本的引入与简单测试 参考资料: Using LD, the GNU linker http://ftp.gnu ...
- S5PV210体系结构与接口04:代码重定位 SDRAM初始化
目录 1. C语言环境初始化 1.1 C语言运行所需环境 1.2 初始化栈 1.2.1 栈的概念 1.2.2 栈的作用 1.2.3 如何初始化 1.3 初始化bss段 1.3.1 bss段的作用 1. ...
- 嵌入式学习(二)——刷机和led实验(看门狗、c语言、icache、重定位、SDRAM)
目录 一.刷机和裸机实验 1.1 刷机步骤 1.2 交叉编译链 1.2.1 环境变量配置 二.led实验 2.1 实验准备 2.2 实验开始 2.2.1 Makefile 2.2.2 mkv210_i ...
- 嵌入式linux-----ARM裸机(5)-----SDRAM和重定位relocate
1.看门狗watch dog timer 现实中因为一些外部因素,电子设备经常会跑飞或者死机(譬如极端炎热.极端寒冷.工业复杂场合).在这种情况下我们希望设备自动复位而不需要人工干预(无人值守).看门 ...
- 韦东山第一期学习笔记——重定位
重定位 说明 必须知道的几个概念 什么是代码重定位? 什么是位置无关码 什么是运行地址 为什么要代码重定位? nand flash启动的情况 nor flash启动的情况 两种方式的重定位 代码重定位 ...
- uboot重定位代码分析(转)
概述 重定位(relocate)代码将BootLoader自身由Flash复制到SDRAM,以便跳转到SDRAM执行.之所以需要进行重定位是因为在Flash中执行速度比较慢,而系统复位后总是从0x00 ...
- PE文件结构详解(六)重定位
前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里 ...
最新文章
- 创新时代的管理:《创新赢天下》
- 天翼云从业认证(4.7)天翼云安全基础实践
- MySQL访问行更新慢、用户线程大量堆积竟是因为它
- “有人拿十几万很开心地走了” 滴滴裁员名额员工竟然抢破头 官方回应...
- 微信公众号可以开店吗?
- 设计模式-命令模式(Command)
- Python计算器练习
- HDU.2111 Saving HDU(贪心)
- PADS2007快捷键、无模命令大全
- QQ应用自动登录最小化功能
- php h m s 转为秒,将m³/s换算为m³/h (立方米每秒换算为立方米每小时)
- 利用Redis的Geo功能实现查找附近的位置!
- CSR867x 之充电配置开发
- 笔记本光驱拆解——让整个世界变得安静
- 学习编程一年需要花费多少?自学可以成为程序员吗?
- DataSet与DataType
- 记一次greenplum集群数据库连接慢的问题定位
- ubuntu下git使用Beyond Compare来做diff和merge方法
- 如何利用边缘计算,实现低延时、高质量的互动课堂体验?
- MP4转gif得力工具
热门文章
- selenium处理动态加载数据
- selenium 3.0鼠标事件 (java代码)
- PHP学习之函数中的全局参数
- springboot 配置过滤器不起作用的原因
- spring中使用i18n(国际化)
- HZNU 2019 Summer training 7
- BZOJ4401: 块的计数 思维题
- 家庭医疗系统-基于蓝牙无线通信技术
- eclipse 改包名
- [Javascript]jquery $(document).ready() 与window.onload的区别