转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>
开发嵌入式软件通常是比较麻烦的事,一些常用的工具往往无法使用,在开发PC软件时简单的任务,此时变得很复杂。今天就遇到了这样一件事,折腾了几个小时,仅仅是为知道call stack。
我编译了一个程序放到PDA(ARM9+LINUX+UCLIBC)上面运行,出现了一个ASSERT,并显示了文件名和行号,原来是调用了一个没有实现的函数,我很想知道是谁调用了它,这看似简单的问题却让我很头疼,如果有gdb,那好办-用bt命令就可以搞定,如果用的libc,那也好办-用backtrace函数就可以搞定,问题是两者都没有。
想来想去只有自己写一个backtrace,要实现这个功能并不难,如果我们知道调用堆栈的格式,就可以很容易取出上层调用者的指令地址,有了这些上层调用者的指令地址,我们可以通过MAP文件找到指令地址对应的源文件名和行号。
下面简要介绍一下实现原理:
要获得调用者的地址,有必要介绍一下堆栈的格式:
+---------------------------+ (高地址)
+_参数1__________+
+---------------------------+
+_参数2__________+
+---------------------------+ 参数的顺序依赖于调用方式
+_参数.__________+
+---------------------------+
+_参数N__________+
+---------------------------+
+_eip____________+ 返回本次调用后,下一条指令的地址
+----------------------------+
+_ebp____________+ 这里保存的调用者的ebp
+----------------------------+
(ebp 指向这里:相当于调用者和被调用者的分界线)
+----------------------------+
+_临时变量1_______+
+----------------------------+
+_临时变量2_______+
+----------------------------+
+_临时变量.________+
+----------------------------+
+----------------------------+
+_临时变量N_______+
+----------------------------+(低地址)
由于优化、调用方式、编译器的不同,上述布局部可能有所不同,但一般来说,第一个局部变量前是调用者的ebp,ebp前是返回后下一条指令的地址。
知道了这个结构,要获得上层调用的者指令地址就容易了,我们可以用如下代码模拟glibc提供的backtrace的功能:
int backtrace (void **BUFFER, int SIZE)
{
int n = 0;
int *p = &n;
int i = 0;
int ebp = p[1];
int eip = p[2];
for(i = 0; i < SIZE; i++)
{
BUFFER[i] = (void*)eip;
p = (int*)ebp;
ebp = p[0];
eip = p[1];
}
return SIZE;
}
附:
通过addr2line可以找到地址对应的文件名和行号,不用手动去查MAP文件了。
分享到:
相关推荐
前端开源库-eslint-config-callstack-ioeslint配置callstack io,eslint预设扩展airbnb,流,prettier和jest
最近发布的Zstack 3.0.2 SDK 和说明文档
npm install --save react-native-card-stack-swiper 预习 import CardStack , { Card } from 'react-native-card-stack-swiper' ; < CardStack xss=removed xss=removed xss=removed> { this . swiper = swiper ...
linux协议栈源码,带注释版本,是学习linux tcp/ip协议栈的最佳伴侣。 linux内核版本2.6
Bring-the-cloud-to-your-datacenter-Microsoft-Azure-Stack,Bring-the-cloud-to-your-datacenter-Microsoft-Azure-Stack
python-flask-and-django-full-stack-python-for-web-development
该BACnet协议栈库 提供了BACnet应用层,网络层和媒体访问(MAC)层通信服务。它是适用于嵌入式系统,Windows,Linux或其他操作系统的开源免版税库。 包括示例BACnet客户端和服务器应用程序。
linux内核网络协议栈源码阅读分析注释--带详尽中文分析注释以及相关流程分析调用注释,对理解分析内核协议栈源码很有帮助
SpringMVC精品资源--ReactJS-Spring-Boot-Full-Stack-App
前端大厂最新面试题-implement-queue-using-stack.docx
Berkeley-Data-Analytics-Stack-BDAS-Overview-Ion-Stoica-Strata-2013.pdf
Ansible-django-angular2-fullstack-devops.zip,使用ansible/packer/terraformdjango-angular2-fullstack-devops在aws上实现多环境devops的一体化django/angular2 seed和cli接口,ansible是一个简单而强大的自动化...
前端项目-knockback-core-stack,knockback.js为主干.js模型和集合提供knockout.js魔力
Ajax-Job-Portal-Full-Stack-Web-Application.zip,网络开发工具与方法课程学术计划,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中网页的小...
京东智联云-专有云JD Cloud Stack白皮书-2020.3.rar
Ansible-ansible-flask-stack.zip,Ansible角色设置和部署烧瓶应用程序。Ansible-FlaskApp,ansible是一个简单而强大的自动化引擎。它用于帮助配置管理、应用程序部署和任务自动化。
Ansible-vagrant-elastic-stack.zip,试谈盒子中的弹性叠,ansible是一个简单而强大的自动化引擎。它用于帮助配置管理、应用程序部署和任务自动化。
特征在React和React Native中工作createTheming(defaultTheme) -工厂返回: ThemeProvider组件withTheme高阶组件useTheme -React Hook例子Web react的内置示例-入门安装npm install --save @callstack/react-theme-...
Angular-full-reactive-stack.zip,带spring boot(webflux)、mongodb和angularfull reactive stack的全反应堆栈,Angularjs于2016年发布,是Angularjs的重写版。它专注于良好的移动开发、模块化和改进的依赖注入。...