armclang 使用 instrument function 分析函数执行流程

6 篇文章 0 订阅

1、添加编译选项

armcc 编译选项添加 --gnu_instrument  (比如 CFLAGS += --gnu_instrument)

armclang 编译选项添加 -finstrument-functions (比如 CFLAGS +=  -finstrument-functions)

 

2、申明 instrument 函数

void __cyg_profile_func_enter(void *this, void *callsite)__attribute__((no_instrument_function));

void __cyg_profile_func_exit(void *this, void *callsite)__attribute__((no_instrument_function));

 

3、定义 instrument 函数

void __cyg_profile_func_enter( void *this, void *callsite )
{
  fprintf(fp, "E%p\n", (int *)this);
}


void __cyg_profile_func_exit( void *this, void *callsite )
{
  fprintf(fp, "X%p\n", (int *)this);
}

这里输出当前函数的地址(instrument 函数: __cyg_profile_func_enter 和 __cyg_profile_func_exit  会分别在使用 -finstrument-functions 或  --gnu_instrument 编译过的模块函数进入和退出时自动调用, 这两个函数的第一个参数是当前函数的函数地址,第二参数是调用该函数的函数地址).

 

4、分析maps 文件

编译器生成的maps 文件,其中生成的函数段格式如下:

    function1                        0x882f29a9   Thumb Code    28  module.o(.text)
    function2                        0x882f2861   Thumb Code    28  module.o(.text)

假设 maps 文件名为 arm.map

 

5、运行程序得到 instrument 函数输出的函数地址

运行使用 instrument 函数重新编译过的模块,假设 fp 的文件名是 addr.txt, 运行程序后addr.txt 的内容如下

E0x882f29a9
E0x882f2861
X0x882f2861
X0x882f29a9

6、将输出的函数地址转换为函数名

原理很简单,就是到 map 文件中通过函数地址,找到对应的函数名称,这个过程我们使用 Pyhon 脚步完成

$ python3 addr2name.py arm.map addr.txt
Start address to name
function1
function2
 

 

addr2name.py 源码如下:

import sys

def find_name(fmap_name, addr):
    result=""
    with open(fmap_name, 'r') as fmap:
        for line in fmap:
            if line.find(addr) == -1:
                continue
            if line.split()[1] == addr:
                result = line[:]
                break
 
    return result


def main():
    print('Start address to name')
    fmap_name = sys.argv[1]
    faddr_name = sys.argv[2]

    with open(faddr_name, 'r') as faddr:
        for addr in faddr:
            #print(repr(addr))
            addr = addr.strip()
            if not addr.startswith("E"):
                continue
            line = find_name(fmap_name, addr[1:])
            print(line.split()[0]);
    

if __name__ == '__main__':
    main()

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值