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

 更新时间:2023年02月03日 15:36:04   作者:水火汪  
这篇文章主要介绍了C/C++程序链接与反汇编工具objdump的使用,程序构建过程的第二个阶段就是链接,链接过程输入的是目标文件的集合。每个目标文件可以被看作单个源代码文件的二进制存储版本

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

链接阶段

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

1.重定位

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

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

2.解析引用

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

function.h代码:

#pragma once
#define FIRST_OPTION
#ifdef FIRST_OPTION
#define MULTIPLIER (3.0)
#else
#define MULTIPLIER (2.0)#endif
float add_and_multiply(float x,float y);

function.c

//#include "function.h"
int nCompletionStatus = 0;
float add(float x,float y)
{
   float z = x + y;
   return z;
}
float add_and_multiply(float x,float y)
{
   float z = add(x,y);
   z *= 3;
   return z;
}

main.c

#include "function.h"
extern int nCompletionStatus;
int main(int argc,char* argv[])
{
    float x = 1.0;
    float y = 5.0;
    float z;
    z= add_and_multiply(x,y);
    nCompletionStatus =1;
    return 0;
}

在上例代码中

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

该问题如图描述:

function.o

main.o

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

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

3.链接示例

程序内存映射图

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

反汇编main.o文件

objdump -D -M intel main.o

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

反汇编demoApp

objdump -D -M intel demoApp

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

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

objdump -x -j .bss demoapp

到此这篇关于C/C++程序链接与反汇编工具objdump的使用介绍的文章就介绍到这了,更多相关C++程序链接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言fgetc和fputc函数用法详解(以字符形式读写文件)

    C语言fgetc和fputc函数用法详解(以字符形式读写文件)

    这篇文章主要介绍了C语言fgetc和fputc函数用法详解(以字符形式读写文件),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • C++程序中main(int argc, char *argv[])函数的参数意义

    C++程序中main(int argc, char *argv[])函数的参数意义

    这篇文章主要介绍了C++程序中main(int argc, char *argv[])函数的参数意义,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • C++ 位图及位图的实现原理

    C++ 位图及位图的实现原理

    位图实际上就是一个数组,因为数组有随机访问的功能,比较方便查找,这个数组一般是整形,今天通过本文给大家分享c++位图的实现原理及实现代码,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • C++/Qt遍历多维数组的3种方式示例

    C++/Qt遍历多维数组的3种方式示例

    一维数组对于存储和处理一组数据很有用,但有时候,有必要使用多维数组,下面这篇文章主要给大家介绍了关于C++/Qt遍历多维数组的3种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • C++List容器常用函数接口刨析

    C++List容器常用函数接口刨析

    最近我学习了C++中的STL库中的list容器,对于常用容器,我们不仅要会使用其常用的函数接口,我们还有明白这些接口在其底层是如何实现的。所以特意整理出来一篇博客供我们学习
    2022-08-08
  • 如何用矩形法(梯形法)求定积分

    如何用矩形法(梯形法)求定积分

    思路就是将积分区间划分成n等份,然后将这n等份近似看成矩形(或梯形),然后对所有的矩形(或梯形)的面积进行求和
    2013-09-09
  • C语言数据结构 链表与归并排序实例详解

    C语言数据结构 链表与归并排序实例详解

    这篇文章主要介绍了C语言数据结构 链表与归并排序实例详解的相关资料,需要的朋友可以参考下
    2017-01-01
  • OpenCV实现图像距离变换

    OpenCV实现图像距离变换

    这篇文章主要为大家详细介绍了OpenCV实现图像距离变换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C语言实现扫雷小游戏的示例代码

    C语言实现扫雷小游戏的示例代码

    这篇文中主要为大家详细介绍了如何利用C语言实现经典的扫雷小游戏。扫雷小游戏主要是利用字符数组、循环语句和函数实现,感兴趣的小伙伴可以了解一下
    2022-10-10
  • C语言入门篇--初识指针和指针变量

    C语言入门篇--初识指针和指针变量

    本篇文章是基础篇,适合c语言刚入门的朋友,本文对初识c语言的指针和指针变量做了简单的分析,帮助大家快速入门c语言的世界,更好的理解c语言
    2021-08-08

最新评论