设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间15 现在时间15 缓存数据 一个人挺好的

一个人挺好的 -- 一个

查看: 596|回复: 0

C/C++程序链接与反汇编工具objdump的使用介绍

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:223
  • 打卡月天数:0
  • 打卡总奖励:3404
  • 最近打卡:2025-04-20 18:46:21
等级头衔

等級:晓枫资讯-上等兵

在线时间
3 小时

积分成就
威望
0
贡献
368
主题
339
精华
0
金钱
4496
积分
749
注册时间
2023-1-14
最后登录
2025-4-20

发表于 2023-2-5 19:44:14 | 显示全部楼层 |阅读模式

程序构建过程的第二个阶段就是链接,链接过程输入的是目标文件的集合。每个目标文件可以被看作单个源代码文件的二进制存储版本,需要为程序内存映射提供各种各样的节(代码.text 初始化数据.data 未初始化数据.bss 和只读数据.rdata),链接器的最终任务是将独立的节组合成最终的程序内存映射节,与此同时解析所有的引用。


链接阶段

链接过程包括一系列阶段(重定位、解析引用),接下来我们介绍这些阶段。


1.重定位

链接过程的第一个阶段仅仅进行拼接,其过程是将分散在单独目标文件中不同类型的节拼接到程序内存映射节中。

如图,为了完成任务,需要将之前预留的空间,也就是节中从0开始的地址范围转换成最终程序内存映射中更具体的地址范围。

2023020315220910.png


2.解析引用

现在我们来看链接过程中最难的部分,将节的地址范围线性地转换成程序内存映射地址范围。相比来说,更艰巨的任务在于为不同的部分的代码建立关联,使得程序成为一个整体。

function.h代码:

  1. #pragma once
  2. #define FIRST_OPTION
  3. #ifdef FIRST_OPTION
  4. #define MULTIPLIER (3.0)
  5. #else
  6. #define MULTIPLIER (2.0)#endif
  7. float add_and_multiply(float x,float y);
复制代码

function.c

  1. //#include "function.h"
  2. int nCompletionStatus = 0;
  3. float add(float x,float y)
  4. {
  5.    float z = x + y;
  6.    return z;
  7. }
  8. float add_and_multiply(float x,float y)
  9. {
  10.    float z = add(x,y);
  11.    z *= 3;
  12.    return z;
  13. }
复制代码

main.c

  1. #include "function.h"
  2. extern int nCompletionStatus;
  3. int main(int argc,char* argv[])
  4. {
  5.     float x = 1.0;
  6.     float y = 5.0;
  7.     float z;
  8.     z= add_and_multiply(x,y);
  9.     nCompletionStatus =1;
  10.     return 0;
  11. }
复制代码

在上例代码中

  • add_and_multiply 函数调用add函数,这两个函数在同一个源代码文件中,这种情况下,函数add的内存映射地址是一个已知量,会被扩展成其对与function.o中代码节起始地址的相对偏移。
  • main函数会调用add_and_multiply函数,并同时引用外部变量nCompletionStatus,这个时候问题就出现了--我们不知道它们的实际程序内存地址,实际上编译器会假定这些符号未来会在进程内存映射中存在,但是,直到生成完整内存映射之前,这两个引用会一直被当成未解析引用。

该问题如图描述:

function.o

2023020315220911.png

main.o

2023020315220912.png

为了解决这类问题,我们需要在链接阶段就对这些引用进行解析,此时链接器需要:

  • 检查拼接到程序内存映射中的节
  • 找出那些部分代码产生了外部调用
  • 计算该引用的精确地址(在内存映射中的地址)
  • 最后,将机器指令中的伪地址替换成程序内存映射的实际地址,这样就完成了引用的解析。

3.链接示例

程序内存映射图

2023020315220913.png

gcc -c function.c main.c
gcc function.o main.o -o demoApp

反汇编main.o文件

objdump -D -M intel main.o

划红线的是跳转自身,是因为链接器不知道函数的地址。先用伪地址代替。

2023020315220914.png

反汇编demoApp

objdump -D -M intel demoApp

画红线的位置分别是add_and_multiply 地址为11aa 和nCompletionStatus的地址。

2023020315220915.png

2023020315220916.png

执行下面命令查看,看到nCompletionStatus地址为4014.

objdump -x -j .bss demoapp

2023020315220917.png

到此这篇关于C/C++程序链接与反汇编工具objdump的使用介绍的文章就介绍到这了,


晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表