获取Android Native堆栈

文章目录

    • 工具和方法
    • 获取当前线程的堆栈信息
    • 获取任意线程的堆栈信息
    • GCC生成符号的规律
    • 总结

在Android系统中,我们有时需要获取Native层的堆栈信息,例如在进行性能分析、问题定位和调试等场景。本文将介绍如何在Android Native层获取堆栈信息,并提供示例代码。

工具和方法

在Android系统中,我们可以使用backtrace函数来获取当前线程的堆栈信息。backtrace函数是GNU libc库提供的一个函数,它可以获取当前线程的调用堆栈。此外,Android NDK还提供了unwind.h头文件,其中定义了unwind函数,可以用于获取任意线程的堆栈信息。

获取当前线程的堆栈信息

我们可以使用backtrace函数获取当前线程的堆栈信息。以下是使用backtrace函数获取堆栈信息的示例代码:

#include <execinfo.h>
#include <stdio.h>void print_backtrace() {const int max_frames = 128;void* frame[max_frames];int frame_count = backtrace(frame, max_frames);char** symbols = backtrace_symbols(frame, frame_count);if (symbols) {for (int i = 0; i < frame_count; ++i) {printf("%s\n", symbols[i]);}free(symbols);}
}

在上述代码中,backtrace函数会将当前线程的调用堆栈的地址保存到frame数组中,然后我们使用backtrace_symbols函数将这些地址转换为对应的函数名。

获取任意线程的堆栈信息

如果我们需要获取任意线程的堆栈信息,可以使用Android NDK中的unwind函数。以下是使用unwind函数获取堆栈信息的示例代码:

#include <unwind.h>
#include <dlfcn.h>
#include <stdio.h>struct BacktraceState {void** current;void** end;
};_Unwind_Reason_Code unwind_callback(struct _Unwind_Context* context, void* arg) {BacktraceState* state = static_cast<BacktraceState*>(arg);uintptr_t pc = _Unwind_GetIP(context);if (pc) {if (state->current == state->end) {return _URC_END_OF_STACK;} else {*state->current++ = reinterpret_cast<void*>(pc);}}return _URC_NO_REASON;
}void capture_backtrace(void** buffer, int max) {BacktraceState state = {buffer, buffer + max};_Unwind_Backtrace(unwind_callback, &state);
}void print_backtrace(void** buffer, int count) {for (int idx = 0; idx < count; ++idx) {const void* addr = buffer[idx];const char* symbol = "";Dl_info info;if (dladdr(addr, &info) && info.dli_sname) {symbol = info.dli_sname;}printf("%-3d %p %s\n", idx, addr, symbolvoid print_backtrace(void** buffer, int count) {for (int idx = 0; idx < count; ++idx) {const void* addr = buffer[idx];const char* symbol = "";Dl_info info;if (dladdr(addr, &info) && info.dli_sname) {symbol = info.dli_sname;}// 计算相对地址void* relative_addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) - reinterpret_cast<uintptr_t>(info.dli_fbase));printf("%-3d %p %s (relative addr: %p)\n", idx, addr, symbol, relative_addr);}
});}
}

在上述代码中,capture_backtrace函数使用_Unwind_Backtrace函数获取堆栈信息,然后我们使用dladdr函数获取到函数所在的SO库的基地址(info.dli_fbase),然后计算出函数的相对地址(relative_addr)。然后在打印堆栈信息时,同时打印出函数的相对地址。

GCC生成符号的规律

Native堆栈的符号信息跟代码中定义的函数名字相比,可能会有一些差别,因为GCC生成的符号表有一些修饰规则。GCC在编译C/C++等语言源代码时,会生成相应的符号。这些符号主要用于链接时解析和调试等目的。GCC生成的符号遵循一定的规则,主要包括以下几点:

  1. 名字修饰(Name Mangling):
    C++支持函数重载,即同一个函数名可以有不同的参数类型和个数。为了在编译时区分这些函数,GCC会对函数名进行修饰,生成独特的符号名称。修饰后的名称包含了函数名、参数类型等信息。例如,对于如下C++函数:
namespace test {int foo(int a, double b);
}

经过GCC修饰后,生成的符号可能类似于:_ZN4test3fooEid,其中:

  • _ZNE是修饰前缀和后缀,用于标识这是一个C++符号。
  • 4test表示命名空间名为test4表示命名空间名的长度。
  • 3foo表示函数名为foo3表示函数名的长度。
  • id表示函数的参数类型,i代表intd代表double
  1. 变量符号:
    全局变量和静态变量的符号名称通常与其在源代码中的名称相同。局部变量的符号名称会包含函数名和变量名,以及作用域信息。

  2. 符号可见性(Symbol Visibility):
    根据符号在源代码中的声明,GCC会为生成的符号分配不同的可见性。例如:

  • static:局部符号,只在当前源文件内可见。
  • extern:外部符号,可以在其他源文件中使用。
  • 默认:如果没有指定staticextern,则符号的可见性取决于编译器的默认设置。
  1. 弱符号和强符号:
    弱符号(Weak Symbol)是可以被其他同名符号覆盖的符号,而强符号(Strong Symbol)是不会被覆盖的。当链接器在链接过程中遇到同名的强符号和弱符号时,会选择强符号。在GCC中,可以使用__attribute__((weak))修饰符来声明弱符号。

了解GCC生成符号的规律有助于我们在分析和调试程序时快速定位函数和变量,以及理解链接器在链接过程中如何处理这些符号。

总结

获取Android Native堆栈信息是Android性能分析和问题定位的重要手段。通过使用backtraceunwind函数,我们可以方便地获取到堆栈信息,并进行后续的分析和处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/7603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉——OpenCV Otsu阈值法原理及实现

算法简介 Otsu阈值法&#xff0c;也被称为大津算法&#xff0c;是一种在图像处理中广泛使用的自动阈值分割技术。这种方法由日本学者大津展之于1979年提出&#xff0c;旨在根据图像的灰度直方图来自动选择最佳全局阈值。Otsu阈值法的核心思想是最小化类内方差或最大化类间方差…

《设计一款蓝牙热敏打印机》

主控芯片用易兆威蓝牙ic&#xff0c;通讯接口&#xff1a;蓝牙、串口、usb 安卓apk用java kotlin编写、上位机用Qt编写。

【微磁学】对于现阶段微磁学仿真发展的思考1-理论篇

系列文章目录 对于现阶段微磁学仿真发展的思考1-理论篇 对于现阶段微磁学仿真发展的思考2-工具篇 文章目录 系列文章目录前言一、微磁学的数学区二、微磁学的物理区三、微磁学仿真现存的一些问题四、微磁学代码区&#xff1a;上手操作&#xff0c;理解更深入栗子1: 能量最小化…

【代码随想录】day50

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、123买卖股票的最佳时机III二、188买卖股票的最佳时机IV 一、123买卖股票的最佳时机III 超时了。。。 class Solution { public:int helper(vector<int>…

lsof 查看进程是被哪个文件占用

要查看进程被哪个文件占用&#xff0c;可以使用lsof命令&#xff08;list open files&#xff09;。可以使用以下命令来查看指定进程的打开文件&#xff1a; lsof -p <PID>其中&#xff0c;<PID>是要查询的进程的进程ID。这将列出指定进程打开的所有文件。如果想查…

WouoUIPagePC端实现

WouoUIPagePC端实现 WouoUIPage是一个与硬件平台无关&#xff0c;纯C语言的UI库&#xff08;目前只能应用于128*64的单色OLED屏幕上&#xff0c;后期会改进&#xff0c;支持更多尺寸&#xff09;。因此&#xff0c;我们可以在PC上实现它&#xff0c;本文就以在PC上使用 VScode…

Java面试题:Spring里面的@RestController和@ResponseBody有什么作用?

ResponseBody ResponseBody一般是加在方法上&#xff0c;将返回的对象解析成xml或者json&#xff0c;返回给请求的调用者。一般是用于服务之间的调用&#xff0c;或者前端请求后端时&#xff0c;使用ajax请求。 如果不加ResponseBody&#xff0c;一般就是返回的url&#xff0c…

研发效能 | Jacoco dump基于k8s的实现

问题描述 总所周知&#xff0c;jacoco的dump操作如果是使用server模式只需要使用以下命令就能获取到 exec 文件。 java -jar jacococli.jar dump --address 192.169.110.1 --port 6300 --destfile ./jacoco-demo.exec 如果是非 k8s 的集群&#xff0c;也只需要遍历执行这条命…

Python实现打砖块游戏

提供学习或者毕业设计使用&#xff0c;功能基本都有&#xff0c;不能和市场上正式游戏相提比论&#xff0c;请理性对待&#xff01; 在本文中&#xff0c;我们将使用 Pygame 和 Tkinter 创建一个简单的打砖块游戏。游戏的目标是通过控制挡板来击碎屏幕上的砖块&#xff0c;同时…

基于 OpenHarmony compress 三方件使用指南~

关于 提供了一个轻量级的图像压缩库。将允许您将大照片压缩成小 尺寸的照片&#xff0c;图像质量损失或可以忽略不计 compress 的依赖添加 为你的应用添加 compress-debug.har。将 compress-debug.har 复制到 entry\libs 目录下即可&#xff08;由于 build.gradle 中已经依赖…

HALPWM配置占空比频率2按键控制思路

title: HALPWM配置占空比频率 tags: STM32ClionHal 控制pwm开关 //启动定时器 HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);//关闭定时器 HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);//启动指定通道PWM HAL_StatusTypeDef HAL_TIM_P…

【负载均衡式在线OJ项目day1】项目结构

一.功能 查看题目列表&#xff0c;在线编程&#xff0c;判题功能&#xff0c;即leetcode的部分功能 二.宏观结构 整个项目是BS模式&#xff0c;客户端是浏览器&#xff0c;和用户交互并向服务器发起请求。 服务端从功能上来说分为两个模块&#xff0c;第一个是OJServer&…

小红书餐饮推广怎么合作?纯干货

小红书作为国内领先的生活方式分享平台&#xff0c;其用户群体主要集中在一二线城市&#xff0c;年龄分布在18-35岁之间&#xff0c;其中女性用户占比高达80%。这部分用户具有较高的消费能力、审美追求和品质生活需求&#xff0c;对美食有着极高的兴趣和消费意愿&#xff0c;为…

Mysql 行格式 innodb_default_row_format 可以配置那些值, 有什么区别

在MySQL中&#xff0c;innodb_default_row_format选项指定了InnoDB表创建时的默认行格式。这个设置对于新创建的表非常重要&#xff0c;因为它影响了数据的存储方式、空间利用率和性能。innodb_default_row_format可以配置为以下几个值&#xff0c;每个值代表不同的行格式&…

【计算机网络】计算机网络的性能指标

计算机网络的性能指标被用来从不同方面度量计算机网络的性能。常用的八个计算机网络性能指标&#xff1a;速率、带宽、吞吐量、时延、时延带宽积、往返时间、利用率、丢包率。 一.速率 (1) 数据量 比特&#xff08;bit&#xff0c;记为小写b&#xff09;是计算机中数据量的基…

python使用mongo操作

目前有个需求&#xff0c;就是把所有sql转为mongo管道查询 知识点 在 MongoDB 中&#xff0c;allowDiskUse 选项应该作为聚合命令的一个选项&#xff0c;而不是聚合管道的一个阶段。allowDiskUse 选项用于允许聚合操作使用磁盘空间来临时存储数据&#xff08;当聚合操作的数据…

力扣顺序表思路讲解

本篇文章&#xff0c;我给大家带来的是顺序表题目讲解&#xff0c;希望大家看完有所收获&#xff0c;废话不多说&#xff0c;我们现在开始 审题 大白话&#xff1a;给了一个数组和一个目标值。如果数组里的两个元素相加 目标值&#xff0c;则返回这两个元素的下标。那么大家需…

java编程中,实现分页对象的类型转换

一、背景 当数据库分页查询返回的对象与接口要返回的对象类型不一致时&#xff0c;不可避免需要进行类型转换。 示例&#xff1a;数据库分页查询返回的对象是PageDTO&#xff0c;而接口返回的对象类型是PageVO。 PageDTO Data public class PageDTO<T> {/*** Current…

Python专题:一、安装步骤

1、下载地址&#xff1a;Welcome to Python.org 勾选这个add 其他的全部下一步即可。 运行出现这个即代表安装成功。 Python自带编辑器。 2、推荐使用的sublime 编辑器下载 全部下一步安装。

C++ 函数与指针

函数内部数据是地址需要传递给调用函数&#xff0c;返回的当然是指针了&#xff01;当然&#xff0c;这个返回地址也可以通过函数参数返回&#xff01; 函数的参数是指针可以输出函数多个结果&#xff0c;返回值本身就是返回数据&#xff0c;什么时候需要返回指针呢&#xff1f…