38 如何根据地址获取函数名

[Python] 获取当前函数名的三种方法 输出:get_fun_name_1。输出:get_fun_name_2。输出:get_fun_name_3。可以用来获取当前函数的句柄,返回。使用下面的代码获取函数的名称。函数内和函数外都可以用。来获取的函数运行信息。 阅读详情

38.1 前言

之前有做过一个通过截取内核信号,获取程序出错所在函数位置信息(如段错误),然后进行栈回溯的功能(之前的blog有写),那个虽然成功了,但仍有一些不合人意的地方。就是手动回溯结果显示的只是函数地址,如果要看是哪个函数,那还要用objdump或addrline工具用地址找到是哪个函数,比较麻烦。最近折腾了两天时间,终于搞定了根据地址自动获取函数名称的功能。

不管gdb还readelf或addrline工具,可以简单轻松的敲一下命令就可以把函数名及地址整齐地打印展现出来,那么它们是怎么实现的呢??这就是本blog将要讲述的。

38.2 ELF文件及数据结构

首先了解EFL可执行文件,因为我们要找的信息就在ELF文件的符号表中。ELF文件,其全称为Executable and Linking Format,中文语义就是可执行链接格式文件,属于一种文件的存储格式。其有四个部分构成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。如下图示。

相信c/c++软件工程师对程序的数据组织结构有一定的了解,如一个程序有.text段、.bss段、.data段等等,但这些只是属于程序文件中的一部分。一个可执行文件真实的数据组织远不止上述几个,其可能包含二十几个信息区甚至更多,如下图示,在一个elf可执行文件中,其包含了28个section,分别存放着不同的数据。

.bss

未初始化的全局或局部变量

.comment

可执行文件的版本及控制描述信息等

.dynamic

程序动态链接信息及相关属性

.hash

符号hash表

.shstrtab

保存所有节的名称信息

.strtab

保存程序中所有的字符串信息包括函数名

.symtab

符号表

刚才讲到了,ELF头(ELF header)、程序头表(Program header table)、节头表(Section header table)和节(Section),下面就来看一下它们的数据结构是怎样的。

数据类型定义:

/* Type for a 16-bit quantity.  */  
typedef uint16_t Elf32_Half;  
 
/* Types for signed and unsigned 32-bit quantities.  */  
typedef uint32_t Elf32_Word;  
typedef int32_t  Elf32_Sword;  
    
/* Type of addresses.  */  
typedef uint32_t Elf32_Addr;  
  
/* Type of file offsets.  */  
typedef uint32_t Elf32_Off;  
  
/* Type for section indices, which are 16-bit quantities.  */  
typedef uint16_t Elf32_Section;  
  
/* Type for version symbol information.  */  
typedef Elf32_Half Elf32_Versym;  

ELF Header结构(52字节):

#define EI_NIDENT 16  
typedef struct {  
unsigned char e_ident[EI_NIDENT]; //Magic  
Elf32_Half e_type; //文件类型 2-可执行文件  
Elf32_Half e_machine; //机器类型 如arm  
Elf32_Word e_version; //文件版本  
Elf32_Addr e_entry; //程序入口地址  
Elf32_Off e_phoff; //程序头table偏移字节大小  
Elf32_Off e_shoff; //section偏移字节大小  
Elf32_Word e_flags; //processor-specific flags  
Elf32_Half e_ehsize; //elf文件头大小  
Elf32_Half e_phentsize; //程序头大小  
Elf32_Half e_phnum; //程序头数量  
Elf32_Half e_shentsize; //section头大小  
Elf32_Half e_shnum; //section数量  
Elf32_Half e_shstrndx; //字符串表索引节头位置  
} Elf32_Ehdr;  

Program Header结构(32字节):

typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;

Section Header结构(40字节):

typedef struct {
Elf32_Word sh_name; //section名称索引(含义是在string table总的第几个字节数)
Elf32_Word sh_type; //section类型
Elf32_Word sh_flags; //
Elf32_Addr sh_addr; //section的地址
Elf32_Off sh_offset; //section偏移地址
Elf32_Word sh_size; //大小
Elf32_Word sh_link;
Elf32_Word sh_info; //节头信息
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;

Section中的Symbol Table Entry结构(16字节):

typedef struct {
Elf32_Word st_name; //索引值,值为字符串符号表的偏移字节大小(如果是函数那就是函数名)
Elf32_Addr st_value; //符号地址,如果是函数那就是函数地址
Elf32_Word st_size; //
unsigned char st_info; //符号相关信息,如是否为函数、全局类型等等
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;

//注:info转化方式如下。
#define ELF32_ST_BIND(i) ((info)>>4)
#define ELF32_ST_TYPE(i) ((info)&0xf)
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))

38.3 根据地址寻找函数名称思路

对于一个elf文件,其文件内容及组织形式对于不同的文件可能不一样,但一样的是elf文件的文件头对于一种架构来说是一样的,因此若获取elf文件的符号信息等,需要从elf的文件头开始。

 

(1)据上图所示,节头表的起始地址为5388字节开始(即0x150C);

(2)节头大小40字节(即0x28),节头数量29,节头共大小为29*40=1160(即0x488);

(3)节头表数据位置为:0x150C – 0x1994(0x150C+0x488);

(4)由上表可知字符串表索引头:26,因此可以直接在29个节头中定位到字符串索引表头,并获取其中内容;

 

为什么在ELF头中将字符串索引节点给出,那是因为在节头数据结构中,其节section的名字并不是字符串,而只是一个索引值,所有的节名称统一存放在.shstrtab中,因此如果想知道这个section的名称的话,那就需要去找。

        (5)根据名称匹配,可以知道那个section是.symtab符号表,然后拿到其起始地址和大小;

(6)拿到.symtab表起始地址和大小后,以Symbol Table Entry结构大小遍历全部数据。当查找的函数地址与Symbol Table Entry的value匹配时,此时找到对应函数的入口信息点,然后再根据Symbol Table Entry 的name索引值,到.strtab段找到函数名称,此时完成地址与函数名称的查找。

总结流程: 

 

 

38. 函数名举例 即只要传递给myshow的地址是printf函数的地址,这样就可以在任何时候实现对myshow函数的调用。 去接受其它函数的地址值,实现对其它函数的操作。 函数名就是地址,地址就是指针 利用数组指针,可以实现将地址好不相干的几个字符串,实现连续访问。 同理,也可实现函数名也是地址,实现对不同函数的连续访问。 代码要比switch方式实现精简很多 ... 阅读详情

相关推荐

CTFshow-pwn入门-栈溢出pwn37-pwn38

CTFshow pwn入门栈溢出pwn37-38

你们de4月天的博客 1605

在linux程序里面,知道一个函数地址,改函数是属于某个动态库的,怎么样得到这个动态库的全路径名(转)

gnu的扩展函数dladdr可以做到你所要的,man   dladdr可以查到帮助。     另外dl_iterate_phdr可以查到当前进程所装在的所有符号,每查到一个就会调用你指定的回调函数。         下面的代码示例如何使用dl_iterate_phdr和dladdr         #define   _GNU_SOURCE     #include       #include

shark0001的专栏 5709

从Keil的map file中快速找出内存地址对应的函数名

简单实用的一个小工具: 从Keil的map file中快速找出内存地址对应的函数名,快速定位出问题的函数,加速debug的进程。

linux函数地址获取函数名,函数名/函数地址/函数指针

函数指针:1。指针变量 2。指针变量指向函数这正如用指针变量可指向整型变量、字符型、数组一样。在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。可利用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于函数名尽管函数不是变量,但它在内存中仍有其物理地址,该地址...

weixin_29191761的博客 1854

ARM和FPGA之间的通信(硬件原理图篇)

设计该开发板的初衷是为了学习,但也希望今后能扩展其功能,看到大家都在diy示波器,自己也非常冲动的想DIY一把,于是呼选了arm+fpga的方案,fpga主要用来实现数据的高速采样,而ARM则提供数据的显示,以及一些人机交互的功能。那么该方案中最重要的地方就是ARM和FPGA之间的通信如何实现了。在网上查了很多的资料,有说将FPGA作为ARM的一个外设,可以通过DMA的方式来直接访问;也有说把FP

屌yy的博客 5万+

BEVFormer与TensorRT的完美结合:如何实现4倍推理加速?

本文详细解析了如何通过TensorRT的量化技术和自定义插件实现BEVFormer模型的4倍推理加速,同时保持精度损失小于1%。文章从模型架构与部署挑战入手,深入探讨了计算图优化、自定义插件开发和量化校准策略,并提供了完整的部署流程和性能调优技巧,为自动驾驶领域的实时3D感知提供了高效解决方案。

bean的博客 221

c程序如何根据地址获取函数名(addr2line)

38.1 前言 之前有做过一个通过截取内核信号,获取程序出错所在函数位置信息(如段错误),然后进行栈回溯的功能(之前的blog有写),那个虽然成功了,但仍有一些不合人意的地方。就是手动回溯结果显示的只是函数地址,如果要看是哪个函数,那还要用objdump或addrline工具用地址找到是哪个函数,比较麻烦。最近折腾了两天时间,终于搞定了根据地址自动获取函数名称的功能。 不管gdb还readelf或addrline工具,可以简单轻松的敲一下命令就可以把函数名及地址整齐地打印展现出来,那么它们是怎么实现的呢??

赵凯月的博客 3955

高德地图 搜索和点击定位

高德地图vue

weixin_45474673的博客 1943

如何根据地址获取函数名

之前有做过一个通过截取内核信号,获取程序出错所在函数位置信息(如段错误),然后进行栈回溯的功能(之前的blog有写),那个虽然成功了,但仍有一些不合人意的地方。就是手动回溯结果显示的只是函数地址,如果要看是哪个函数,那还要用objdump或addrline工具用地址找到是哪个函数,比较麻烦。最近折腾了两天时间,终于搞定了根据地址自动获取函数名称的功能。......

szembed的博客 1518

LittleFS+NANDFLASH软硬件配置详情

littleFS文件系统说明及移植过程

weixin_43200844的博客 2368

CGAL AlphaShape算法(自适应Alpha值,二维版本)

CGAL AlphaShape算法(自适应Alpha值,二维版本)

dayuhaitang1的博客 2324

Windows x64平台 获取PEB表,并获取kernel32.dll的基址,并获取它的函数

参考了:https://www.cnblogs.com/aliflycoris/p/5185097.html 和另一位博主 话不多说,进入正题: 首先是获取PEB基址,先得懂怎么在64位平台嵌入汇编代码:参考这位博主https://blog.youkuaiyun.com/Giser_D/article/details/90670974 汇编代码: .CODE GetPeb PRO...

MusicMan 5972

借助Gemini 3 Pro高效解决课题申报中的五大核心痛点,亲测有效经验分享

之前给大家分享过关于AI辅助课题申报的相关的内容,涵盖了申报书部分撰写技巧,但没针对性拆解各位同仁在实际申报时遇到的卡壳的地方。比如选题范围拿捏不准,定的太大,根本没法落地完成;定的太小,研究价值则体现不了;写综述时,容易单纯罗列文献,缺乏批判性视角,没办法自然融入自己的判断,找不到研究缺口;研究方法部分,可能担心方法设计不够严谨,别人难以复现.....针对这些申报中的高频痛点,接下来七哥会从五个核心要点出发,借助Gemini 3 Pro高效解决这些痛点。

智能AI让学术科研更容易 701

百度地图根据经纬度获取该地点所在城市信息

请求地址:http://api.map.baidu.com/geocoder/v2/?callback=renderReverse&amp;location=35.658651,139.745415&amp;output=json&amp;pois=1&amp;ak=您的ak密匙 //GET请求 直接放浏览器执行请求就能看到返回结果因为直接放浏览器执行请求就能看到返回结果,因此在这不在举例,如果实...

韩迎宾的博客 2万+

华为OD机试真题 新系统 9月16号 【统计特殊数字】

华为OD新系统机试真题【统计特殊数字】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【统计特殊数字】。

qq_45776114的博客 769

SIMULINK开发项目实例 1000 例专栏之第802例--基于电机驱动系统的场景实例:永磁同步电机(PMSM)在电动汽车中的矢量控制仿真

随着全球对环境保护的关注增加,电动汽车(Electric Vehicle, EV)因其环保特性而受到广泛关注。永磁同步电机(Permanent Magnet Synchronous Motor, PMSM)由于其高效率、高功率密度和良好的动态响应性能,在电动汽车驱动系统中得到了广泛应用。矢量控制(Field-Oriented Control, FOC)是实现PMSM高性能控制的关键技术之一,它能够实现对电机转矩和磁场的独立控制,从而达到类似直流电机的控制效果。本文将详细介绍如何使用来构建一个。

xiaoheshang_123的博客 269

arm里面的链接地址和烧写地址

在考虑为什么要重定位的问题之前,我们首先要明白一下几点: 1. 链接地址的定义:我自己理解是,程序被定义的开始执行的内存地址 在ARM设计中,一般会涉及都一个链接地址,这个链接地址和烧写地址很容易混淆,会认为链接地址就是烧写地址,这个是错的,下面说的是个人的一些认识,可能会有一些错误,说的也可能不专业,但是对于初学者,可以帮助理解。     首先链接地址和烧写地址是两个范畴的东西,几乎是没有关...

明天你好 1256

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Win32 模拟GetProcAddress

1 ;======================= 2 ;模拟GetProcAddress 3 ;函数功能:根据基址和函数名获取函数地址 4 ;参数:_lpBase为基址,_lpBuf为字符串地址 5 ;返回值:函数VA 6 ;======================= 7 _GetApiFromName proc _lpBase,_lpBuf 8 ...

weixin_30545285的博客 203

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

python中的函数名,闭包,迭代器

一.函数名 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数的变量,单纯print()出的是一个内存地址. 1 def func(): 2 print('你说你有点难追') 3 print(func) #<function func at 0x000001F812922EA0> 4 ########################单...

weixin_30278237的博客 97

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

ARM链接地址和烧写地址

在ARM设计中,一般会设计到链接地址和烧写地址,这两个地址概念h

ARM_Tutor的专栏 1510

iOS崩溃日志符号化 & UUID获取

1. 符号表是什么? 符号表就是指在Xcode项目编译后,在编译生成的二进制文件.app的同级目录下生成的同名的.dSYM文件。 .dSYM文件其实是一个目录,在子目录中包含了一个16进制的保存函数地址映射信息的中转文件,所有Debug的symbols都在这个文件中(包括文件名、函数名、行号等),所以也称之为调试符号信息文件。 一般地,Xcode项目每次编译后,都会生成一个新的.dSYM文件。因此...

daxiaoli的博客 2959

ARM 链接地址和烧写地址

在ARM设计中,一般会涉及都一个链接地址,这个链接地址和烧写地址很容易混淆,会认为链接地址就是烧写地址,这个是错的,下面说的是个人的一些认识,可能会有一些错误,说的也可能不专业,但是对于初学者,可以帮助理解。     首先链接地址和烧写地址是两个范畴的东西,几乎是没有关系的,烧写地址,可以认为是物理地址,而链接地址可以认为是虚拟地址,对于程序员来说,看到的是虚拟地址,一般虚拟地址经过MMU映射成

猪哥的专栏 1380

verilog 大小端转换 38译码器 边沿检测 ROM 格雷码计数器

项目场景: `timescale 1ns/1ns module function_mod( input clk, input rst_n, input [3:0]a, input [3:0]b, output [3:0]c, output [3:0]d ); function [3:0] data_rev; // 函数名和返回变量名相同 data_rev input [3:0] din; // 声明输入端口 begin

踩坑记录 664

取得MAC地址的4种方法

 取得MAC地址的4种方法 时间: 2009.02.26 13:25:00 标签:  有需求才有创造,有了问题才会想着去解决,那么我这里的获取MAC地址的第4种方法也是在这种情况下产生的。因为公司有一个服务器产品,要写一个注册模块,而注册模块需要获取硬件信息,而硬件信息有很多,可以是硬盘序列号,CPU序列号,和网卡MAC,我首先使用的是硬盘序列

lionzl的专栏 1560

关于函数指针的一点总结

以前在使用函数指针的时候,没有弄明白函数名和函数指针类型的区别,今天做了个小测试,总结一下测试结果。 int32_t mytest(int32_t id) { printf("my test\n"); return 0; } typedef int32_t (*P_FUN)(int32_t); P_FUN t /*0x00499e0c*/   = mytest /*0x00519

bblueske的专栏 331

获取栈信息

■ API // 获取将backstrace信息,将地址存到buffer中。 // 参数size指定buffer的最大值,返回值则是backstrace的实际大小 int backtrace(void **buffer, int size) // 根据buffer指定的地址,返回符号信息。参数size指定返回符号信息的大小 char ** backtr...

weixin_30273931的博客 161
上一篇: 37 Linux 485收发切换延时导致接收数据错乱问题解决
下一篇: ffmpeg 编程程序 未定义的引用错误问题记录
Chasing_Chasing
博客等级 码龄10年 233粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值