目录

  • 全局变量反汇编与重定位

    • 引入
    • 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

思考这样一个问题,全局变量是怎么存储的,怎么使用的,反汇编后是什么样子的?

  1. 最理想的取地址应该是这样的,但是并没有这样的指令,操作数不可能是一个32位的数

    ldr r0,[a的地址]
  2. 所以我们还想这样,还需要 将 r1 赋值32位的地址..所以单纯的赋值没有办法实现这个操作

    ldr r0,[r1]   
  3. 也就是需要这么做

    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选项和其实发现,单纯的这段maintest代码是一致的

地址分析

 69c:   00008884    .word   0x00008884      ;存放的a的地址的lable6a0:   00008878    .word   0x00008878      ;存放的b的地址的lable6a4:   0000887c    .word   0x0000887c      ;存放的pt的地址的lable

搜索这几个地址值69c6a06a4

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>段重定位数据段就很方便了,将里面的地址挑出来,对其值和其存放的地址都加上偏移即可

  1. 取出a的地址,此时a的地址应该加上offset
  2. a的地址怎么取的,也是从一个lable中取的,这个lable也是经过offset的了
  3. 当a的值是个地址,比如是个函数指针,这个函数指针的值也应该加上offset,才是新定位的函数地址

总结起来一句话

*(adr+offset)=*(adr+offset)+offset

参考文章

uboot的relocation原理详细分析

转载于:https://www.cnblogs.com/zongzi10010/p/10424426.html

全局变量反汇编与重定位相关推荐

  1. linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...

    /// 不需要牛刀,不需要阅读源码,如果只是为解决109的含义.楼主执行的查询命令readelf -S  test2.o [ 8] .symtab           SYMTAB           ...

  2. uboot2012(一)分析重定位

    目录 引入 环境配置 编译体验 入口查找 代码分析 board_init_f pie 内存分布分析 SP设置 board_init_f 重定位 代码段重定位实现 变量地址修改 参考 引入 关于移植,搜 ...

  3. Windows PE第6章 栈与重定位表

    第六章 栈与重定位表 本章主要介绍栈和代码重定位.站和重定位表两者并没有必然的联系,但都和代码有关.栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构. ...

  4. 第013课_代码重定位

    第013课_代码重定位 第013课 代码重定位 1. 段的概念_重定位的引入 2. 链接脚本的引入与简单测试 参考资料: Using LD, the GNU linker http://ftp.gnu ...

  5. 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. ...

  6. 嵌入式学习(二)——刷机和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 ...

  7. 嵌入式linux-----ARM裸机(5)-----SDRAM和重定位relocate

    1.看门狗watch dog timer 现实中因为一些外部因素,电子设备经常会跑飞或者死机(譬如极端炎热.极端寒冷.工业复杂场合).在这种情况下我们希望设备自动复位而不需要人工干预(无人值守).看门 ...

  8. 韦东山第一期学习笔记——重定位

    重定位 说明 必须知道的几个概念 什么是代码重定位? 什么是位置无关码 什么是运行地址 为什么要代码重定位? nand flash启动的情况 nor flash启动的情况 两种方式的重定位 代码重定位 ...

  9. uboot重定位代码分析(转)

    概述 重定位(relocate)代码将BootLoader自身由Flash复制到SDRAM,以便跳转到SDRAM执行.之所以需要进行重定位是因为在Flash中执行速度比较慢,而系统复位后总是从0x00 ...

  10. PE文件结构详解(六)重定位

    前面两篇 PE文件结构详解(四)PE导入表 和 PE文件结构详解(五)延迟导入表 介绍了PE文件中比较常用的两种导入方式,不知道大家有没有注意到,在调用导入函数时系统生成的代码是像下面这样的: 在这里 ...

最新文章

  1. 创新时代的管理:《创新赢天下》
  2. 天翼云从业认证(4.7)天翼云安全基础实践
  3. MySQL访问行更新慢、用户线程大量堆积竟是因为它
  4. “有人拿十几万很开心地走了” 滴滴裁员名额员工竟然抢破头 官方回应...
  5. 微信公众号可以开店吗?
  6. 设计模式-命令模式(Command)
  7. Python计算器练习
  8. HDU.2111 Saving HDU(贪心)
  9. PADS2007快捷键、无模命令大全
  10. QQ应用自动登录最小化功能
  11. php h m s 转为秒,将m³/s换算为m³/h (立方米每秒换算为立方米每小时)
  12. 利用Redis的Geo功能实现查找附近的位置!
  13. CSR867x 之充电配置开发
  14. 笔记本光驱拆解——让整个世界变得安静
  15. 学习编程一年需要花费多少?自学可以成为程序员吗?
  16. DataSet与DataType
  17. 记一次greenplum集群数据库连接慢的问题定位
  18. ubuntu下git使用Beyond Compare来做diff和merge方法
  19. 如何利用边缘计算,实现低延时、高质量的互动课堂体验?
  20. MP4转gif得力工具

热门文章

  1. selenium处理动态加载数据
  2. selenium 3.0鼠标事件 (java代码)
  3. PHP学习之函数中的全局参数
  4. springboot 配置过滤器不起作用的原因
  5. spring中使用i18n(国际化)
  6. HZNU 2019 Summer training 7
  7. BZOJ4401: 块的计数 思维题
  8. 家庭医疗系统-基于蓝牙无线通信技术
  9. eclipse 改包名
  10. [Javascript]jquery $(document).ready() 与window.onload的区别