CN115705294A - 用于获取函数调用信息的方法、装置、电子设备和介质 - Google Patents

用于获取函数调用信息的方法、装置、电子设备和介质 Download PDF

Info

Publication number
CN115705294A
CN115705294A CN202110926882.4A CN202110926882A CN115705294A CN 115705294 A CN115705294 A CN 115705294A CN 202110926882 A CN202110926882 A CN 202110926882A CN 115705294 A CN115705294 A CN 115705294A
Authority
CN
China
Prior art keywords
address
function
stack
code
call
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN202110926882.4A
Other languages
English (en)
Other versions
CN115705294B (zh
Inventor
杨俊杰
王楠
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Huawei Technologies Co Ltd
Original Assignee
Huawei Technologies Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Huawei Technologies Co Ltd filed Critical Huawei Technologies Co Ltd
Priority to CN202110926882.4A priority Critical patent/CN115705294B/zh
Priority to PCT/CN2022/111410 priority patent/WO2023016485A1/zh
Publication of CN115705294A publication Critical patent/CN115705294A/zh
Application granted granted Critical
Publication of CN115705294B publication Critical patent/CN115705294B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Computer Hardware Design (AREA)
  • Quality & Reliability (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Executing Machine-Instructions (AREA)

Abstract

本公开的实施例提供了一种用于获取函数调用信息的方法、装置、电子设备和介质。方法包括从调用栈中获取第一调用返回地址,第一调用返回地址在第一函数的代码的地址范围内;基于第一调用返回地址,在第一函数的代码中确定第一调用代码,该第一调用代码指示由第一函数调用第二函数;以及从第一调用代码中获取第二函数的代码的起始地址。本公开提供的方案不需要寄存器数据就能够获取函数调用信息,因此增加了定位程序出错原因的准确性和适用范围。

Description

用于获取函数调用信息的方法、装置、电子设备和介质
技术领域
本公开的实施例主要涉及计算机技术领域,尤其是操作系统技术。更具体地,本公开的实施例涉及用于获取函数调用信息的方法、装置、电子设备、计算机可读存储介质以及计算机程序产品。
背景技术
在程序开发和维护中,当程序出错(例如,崩溃)后需要查看程序中的函数的调用关系(也称为Call Trace)。Call Trace是指在程序发生问题时把当前函数调用栈打印出来,帮助定位程序出错的原因。
通常,在定位程序出错原因时会使用称为backtrace的方法,其从程序函数调用关系的叶子函数开始,根据寄存器信息和调用栈来推导完整的函数调用关系。然而,对于处理器核挂死导致程序出错的情形,无法获取到处理器核中的寄存器信息,因此也将无法使用backtrace的方法。
发明内容
本公开的实施例提供了用于获取函数调用信息的技术方案。
根据本公开的第一方面,提供了一种用于获取函数调用信息的方法,包括:从调用栈中获取第一调用返回地址,第一调用返回地址在第一函数的代码的地址范围内;基于第一调用返回地址,在第一函数的代码中确定第一调用代码,第一调用代码指示由第一函数调用第二函数;以及从第一调用代码中获取第二函数的代码的起始地址。
根据本公开的实施例,函数的代码被存储在存储器中由编译器确定的代码段的地址范围内,因而作为调用者的第一函数的调用第二函数的代码、以及调用后的返回地址也存储在代码段的地址范围内,并且第二函数的代码的起始地址是指第二函数的首条代码在代码段中的地址。此外,当发生函数调用时,第一函数调用第二函数后的返回地址被压入调用栈。
利用代码段地址范围内的函数代码和压栈机制,根据本公开的获取函数调用信息的方法能够从调用栈获取到第一函数调用第二函数的返回地址,得到调用第二函数的第一调用代码,进而确定在第一调用代码中指示的第二函数的代码的起始地址,由此获取到函数调用信息。因此,根据本公开的方法能够在不需要寄存器数据的情况下解析调用栈而得到函数调用信息,从而扩大了定位程序出错原因的准确性和适用范围。
在一些实施例中,从调用栈中获取第一调用返回地址可以包括:在调用栈中查找在代码段的地址范围内的第一地址,该代码段包括第一函数和第二函数的代码;确定第一地址处的代码的上一条代码是否为跳转指令;以及当该上一条代码为跳转指令时,获取该第一地址作为第一调用返回地址。以此方式,能够检验从调用栈获取的第一地址是否属于函数调用的返回地址,从而提高可靠性和健壮性。
在一些实施例中,在调用栈中查找在代码段的地址范围内的第一地址可以包括:从相对于调用栈的栈底地址的预定偏移处开始,从高地址到低地址在调用栈中查找在代码段的地址范围内的第一地址。以此方式,能够根据操作系统的具体实现方式,有效地确定调用栈中的根函数的栈帧的位置,从而提高查找函数返回地址的效率。
在一些实施例中,调用栈包括第一函数的第一栈帧和第二函数的第二栈帧,第二栈帧包括相邻存储的第一调用返回地址和第一栈帧的栈地址,根据第一方面的方法还可以包括:确定第二函数是否调用了第三函数;以及当确定第二函数调用了所述第三函数时,基于第二栈帧的栈地址,从第三函数的第三栈帧中获取第二调用返回地址,第二调用返回地址在第二函数的代码的地址范围内;基于第二调用返回地址,在第二函数的代码中确定第二调用代码,第二调用代码指示由第二函数调用第三函数;以及从第二调用代码获取第三函数的代码的起始地址。以此方式,能够迭代地从调用栈获取函数调用关系。
在一些实施例中,确定第二函数确定是否调用了第三函数可以包括:确定相对于第二栈帧的栈地址的第一栈地址处是否存在位于第二函数的代码的地址范围内的第二地址并且在相对于所述第二栈帧的栈地址的第二栈帧地址处是否存在第二栈帧的栈地址;如果在第一栈地址处存在该第二地址并且在第二栈地址处存在第二栈帧的栈地址,确定该第二地址处的代码的上一条代码是否为跳转指令;以及如果该上一条代码为跳转指令,确定第二函数调用了第三函数并且获取该第二地址作为第二调用返回地址。以此方式,能够有效地确定当前解析到的函数是否为函数调用中的叶子函数,即,是否调用其他函数,直到解析出所有函数调用信息为止。
在一些实施例中,根据第一方面的方法还可以包括:基于调用栈中存储的第一调用返回地址的栈地址,从第二栈帧中获取第一栈帧的栈地址;基于第二函数的代码的起始地址,获取第二栈帧的大小;以及基于所述第一栈帧的栈地址和所述第二栈帧的大小,确定第二栈帧的栈地址。以此方式,能够有效确定被调用函数的栈帧的栈地址,以便获取进一步的函数调用关系。
在一些实施例中,根据第一方面的方法还可以包括:使用第一调用返回地址从符号表获取第一函数的标识;以及使用第二函数的代码的起始地址从符号表获取第二函数的标识。以此方式,能够从函数的代码的地址获取函数的标识,以得到更容易理解的函数调用信息。
在一些实施例中,根据第一方面的方法还可以包括呈现以下至少一项:第一函数的标识,第二函数的标识,以及指示第一函数调用第二函数的第一调用代码的存储地址。
根据本公开的第二方面,提供了一种用于获取函数调用信息的装置,包括:第一调用返回地址获取单元,被配置用于从调用栈中获取第一调用返回地址,第一调用返回地址在第一函数的代码的地址范围内;调用代码确定单元,被配置用于基于第一调用返回地址在第一函数的代码中确定第一调用代码,第一调用代码指示由第一函数调用第二函数;以及被调函数代码地址获取单元,被配置用于从第一调用代码中获取第二函数的代码的起始地址。
在一些实施例中,第一调用返回地址获取单元还可以被配置用于:在调用栈中查找在代码段的地址范围内的第一地址,该代码段包括第一函数和第二函数的代码;确定第一地址处的代码的上一条代码是否为跳转指令;以及当确定该上一条代码为跳转指令时,获取该第一地址作为第一调用返回地址。
在一些实施例中,第一调用返回地址获取单元还可以被配置用于:从相对于调用栈的栈底地址的预定偏移处开始,从高地址到低地址在调用栈中查找在代码段的地址范围内的第一地址。
在一些实施例中,调用栈包括第一函数的第一栈帧和第二函数的第二栈帧,第二栈帧包括相邻存储的第一调用返回地址和第一栈帧的栈地址。根据第二方面的装置还可以包括函数调用确定单元,该函数调用单元被配置用于确定第二函数是否调用了第三函数。该装置还可以包括第二调用地址返回单元,该第二调用地址返回单元被配置用于当确定第二函数调用了第三函数时,基于第二栈帧的栈地址,从第三函数的第三栈帧中获取第二调用返回地址,第二调用返回地址在第二函数的代码的地址范围内;基于第二调用返回地址,在第二函数的代码中确定第二调用代码,第二调用代码指示由第二函数调用第三函数;以及从第二调用代码获取所述第三函数的代码的起始地址。
在一些实施例中,函数调用确定单元还可以被配置用于:确定在相对于所述第二栈帧的栈地址的第一栈地址处是否存在位于第二函数的代码的地址范围内的第二地址、并且在相对于所述第二栈帧的栈地址的第二栈帧地址处是否存在第二栈帧的栈地址;如果第一栈地址处存在该第二地址并且第二栈地址处存在第二栈帧的栈地址,确定该第二地址处的代码的上一条代码是否为跳转指令;以及如果该上一条代码为跳转指令,确定第二函数调用了第三函数并且获取第二地址作为第二调用返回地址。
在一些实施例中,根据第二方面的装置还可以包括栈帧地址确定单元,栈帧地址确定单元可以被配置用于:基于调用栈中存储的第一调用返回地址的栈地址,从第二栈帧中获取第一栈帧的栈地址;基于第二函数的代码的起始地址,获取第二栈帧的大小;以及基于第一栈帧的栈地址和第二栈帧的大小,确定第二栈帧的栈地址。
在一些实施例中,根据第二方面的装置还可以包括函数标识确定单元,函数标识确定单元可以被配置用于:使用第一调用返回地址从符号表获取第一函数的标识;以及使用第二函数的代码的起始地址从符号表获取第二函数的标识。
在一些实施例中,根据第二方面的装置还可以包括呈现单元,呈现单元可以被配置用于呈现以下至少一项:第一函数的标识,第二函数的标识,以及指示第一函数调用第二函数的第一调用代码的存储地址。
根据本公开的第三方面,提供了一种电子设备,包括处理器和存储器,处理器包括多个处理核,多个处理核中的至少一个处理核被配置用于执行存储器中的指令,使得该电子设备执行根据本公开的第一方面的方法。
根据本公开的第四方面,提供了一种计算机可读存储介质,其上存储有一条或多条计算机指令,其中一条或多条计算机指令被处理器执行使该处理器执行根据本公开的第一方面的方法。
根据本公开的第五方面,提供了一种计算机程序产品,包括机器可执行指令,该机器可执行指令在由设备执行时使所述设备执行根据本申请公开的第一方面所述的方法。
附图说明
结合附图并参考以下详细说明,本申请公开各实施例的上述和其他特征、优点及方面将变得更加明显。在附图中,相同或相似的附图标注表示相同或相似的元素,其中:
图1示出了本公开的多个实施例能够在其中实现的示例环境的示意图;
图2示出了本公开的多个实施例能够在其中实现的另一示例环境的示意图;
图3示出了根据本公开的实施例的用于获取函数调用信息的总体流程的示意流程图;
图4示出了根据本公开的实施例的调用栈的示例示意图;
图5示出了根据本公开的实施例的调用栈的更详细的示意图;
图6示出了根据本公开的实施例的用于获取函数调用信息的过程的示意流程图;
图7示出了根据本公开的实施例的用于获取调用返回地址的过程的示意流程图;
图8示出了根据本公开的实施例的结合代码段来解析调用栈的示意图;
图9示出了根据本公开的实施例的用于确定函数是否为叶子函数的过程的示意流程图;
图10示出了根据本公开的实施例的用于进一步获取函数调用信息的过程的示意流程图;
图11示出了根据本公开的实施例的用于获取函数调用信息的装置的示意框图;以及
图12示出了可以用来实施本公开的实施例的示例设备的示意性框图。
具体实施方式
下面将参照附图更详细地描述本公开的实施例。虽然附图中显示了本公开的某些实施例,然而应当理解的是,本公开可以通过各种形式来实现,而且不应该被解释为限于这里阐述的实施例,相反提供这些实施例是为了更加透彻和完整地理解本公开。应当理解的是,本公开的附图及实施例仅用于示例性作用,并非用于限制本公开的保护范围。
在本公开的实施例的描述中,术语“包括”及其类似用语应当理解为开放性包含,即“包括但不限于”。术语“基于”应当理解为“至少部分地基于”。术语“一个实施例”或“该实施例”应当理解为“至少一个实施例”。术语“第一”、“第二”等等可以指代不同的或相同的对象。下文还可能包括其他明确的和隐含的定义。
如上文所讨论的,在程序开发和维护中,当程序出错后需要查看程序中的函数的调用关系,以便能够定位程序出错的原因。传统的方案通过获取寄存器中数据,例如,程序计数器、栈帧地址,由此回溯函数调用信息。然而,在一些情况下(例如,处理器核挂死),寄存器数据不可用,因此在缺少入口数据的情况下,传统方法无法获取到函数调用信息。
本公开的实施例提供了一种用于获取函数调用信息的方案。利用代码段地址范围内的函数代码和压栈机制,根据本公开的实施例的获取函数调用信息的方法能够在调用栈中查找属于代码段地址范围内的函数调用返回地址,利用该返回地址在代码段确定调用其他函数的代码,由此确定被调用的函数,从而获取到函数调用信息。该方案能够在不需要寄存器数据的情况下获取函数调用信息,从而扩大了定位程序出错原因的准确性和适用范围。以下参照图1至12详细描述本公开的一些示例实施例。
图1示出了本公开的多个实施例能够在其中实现的示例环境100的示意图。环境100是运行计算机程序的计算设备,分为三个层级:硬件层110、操作系统层130、应用层150。硬件层110包括中央处理单元(CPU)111、内存112、存储设备113、输出/输出(I/O)设备114、显示器115。CPU 111可以具有一个或多个处理器核,处理器核执行从内存112加载的计算机程序的代码或指令。内存112存储计算机运行时所需的资源,包括例如计算机程序被编译后得到的汇编代码、变量、堆、栈等数据。取决于环境,汇编代码是可以是ARM、x86、MIPS等体系结构或其各种变体的汇编代码。存储设备113可以用于持久性存储数据。输入/输出(I/O)设备可以包括例如鼠标、键盘、USB设备等。显示器115可以用于向用户呈现程序运行结果或与程序有关的其他信息。应理解,硬件层110可以包括以上描述的更多或更少的硬件设备、以及未在本文中描述的其他硬件设备等。
操作系统层130对接在硬件层110和应用层150之间,提供用户与硬件交互的界面。应用层150可以通过系统调用接口151来访问操作系统中的各个模块。操作系统层130包括软件支持层121、功能实现层133和内核子系统141。软件支持层121包括体系机构模块122、内存管理器126、文件系统127、块设备管理128、字符设备管理129、网络子系统131、网络接口132。功能实现层133包括多任务134、虚拟内存135、文件/目录136、设备访问137、互联性138。内核子系统141包括进程管理141、内存管理142、文件系统143、设备控制、网络145等。应理解,操作系统层110可以包括以上描述的更多或更少的模块、以及未在本文中描述的其他模块等。
如图1所示,体系结构模块122包括栈跟踪模块(StackTrace)123。栈跟踪模块123用于解析与计算机程序有关的调用栈。在计算机程序被执行时,生成由CPU核执行的线程,并且在内存112中为线程分配调用栈,调用栈存储与线程的函数对应的栈帧。取决于操作系统的实现,当发生函数调用时,函数调用信息按照约定方式被存储到栈帧中。在一些实施例中,按照内存的高地址到低地址的方向,根据调用顺序在调用栈中分配函数的栈帧。可以通过解析调用栈来获取线程的函数调用信息。
栈跟踪模块123包括backtrace模块124。反向backtrace模块可以通过获取寄存器中数据,例如,程序计数器、栈帧地址,从调用栈的顶部(低地址)开始解析调用栈,由此回溯函数调用信息。在无法获取寄存器数据的情况下,反向backtrace模块将不可用。根据本公开的实施例,栈跟踪模块123还包括反向backtrace模块125。反向backtrace模块125可以从调用栈的底部(高地址)开始来解析调用栈,并且不需要使用CPU 111的寄存器数据。另外,用于获取函数调用信息backtrace模块124和反向backtrace模块125被实现在操作系统层软件支持层121,属于操作系统内核的基本功能,可以由功能实现层133和内核子系统层141中的任何模块在需要获取函数调用信息时调用。
图2示出了本公开的多个实施例能够在其中实现的另一示例环境200的示意图。环境200包括CPU 210、操作系统内核230和用户级进程250。操作系统内核230包括TRAPS模块231、栈跟踪模块223、体系结构222、线程调度器231、内核线程232-1和232-2、进程233以及与线程和进程有关的数据,例如线程控制块、代码、全局变量、堆、栈等。用户级进程250在操作系统内核之上,包括进程251和252,其中每个进程可以具有一个或更多个线程,例如线程A和线程B。在一些实施例中,在同一进程中的多个线程可以共享代码、全局变量和堆,并且具有各自的调用栈。应理解,CPU的210的核的数目、进程和线程的数目不限于图中示出的数目,CPU 210可以包括更多或更少的核心,并且操作系统内核230和用户级进程250可以包括更多或更少的进程和线程。
如图2所示,栈跟踪模块223包括backtrace模块224和反向backtrace模块225。本公开的实施例可以被实现在操作系统内核230的栈跟踪模块(stacktrace)223中的反向backtrace模块225中。如上所述,根据本公开的实施例的反向backtrace模块能够在传统的backtrace模块不可用时,解析调用栈来获取函数调用信息。
在一些实施例中,线程调度器231可以调度进程或线程在某一个核上执行,当发生CPU核挂死的事件时,操作系统内核230中的TRAPS模块231能够检测到该事件。在这种情况下,可以调用栈跟踪模块223中的反向backtrace模块来获取该CPU核心上的进程或线程的函数调用信息。
图3示出了根据本公开的实施例的用于获取函数调用信息的总体流程300的示意流程图。在流程300开始处发生了CPU核挂死。在框302,该CPU核触发不可屏蔽中断(NMI),并且NMI被上报到操作系统内核的TRAPS模块231。
然后,在框304,TRAPS模块231确定发生挂死的CPU核号,并且确定将用于执行反向backtrace方法的工作CPU核号。
在框306,判断发生CPU核挂死时操作系统处于用户态还是内核态。当确定处于内核态时,在框308,转储(dump)内核内存。由于在内存、CPU、I/O等设备上的数据都是动态易失的,也就是说数据使用完或者发生异常就会丢掉。为了得到这些数据以便分析,例如调试程序,需要将内存中的数据转储为静态(例如文件)的形式。因此,可以通过将内核地址空间中的数据保存为文件的形式来转储内核内存。然后,在框310,获取内核进程的线程控制块(TCB)。线程控制块描述描述线程,包括例如线程标识符、线程状态、线程相应的代码和数据地址、线程的资源清单、线程的优先级、CPU现场保护信息、用于线程之间的通信的信号等。当确定处于用户态时,在框312,转储用户面内存。也就是说,将用户地址地址空间中的数据保存为文件。由于不同的用户拥有不同的地址空间,因此在框314,构造相同用户面地址空间。由此,在分析用户级程序时,所有用户级程序具有统一的地址空间。然后,在框316,获取用户面线程控制块316。类似地,用户面线程控制块描述对应用户级线程。
在获取到经转储的内存数据和对应的线程控制块之后,在框318,执行反向backtrace方法。如上所述,根据本公开的实施例的反向backtrace方法能够在CPU挂死的情况下获取函数调用信息。在框320,记录函数调用信息。函数调用信息可以被用于定位程序发生问题的位置和原因。
以下参照图4至图10描述根据本公开的实施例的反向backtrace方法。在描述反向backtrace方法之前说明线程数据是如何存储在内存中是有帮助的。线程的地址空间包括与该线程有关的代码段、符号起始块(BSS)段、数据段、堆、栈等。同一进程的多个线程可以共享代码段、符号起始块(BSS)段、数据段、堆。代码段也被称为文本段,指代用于存放程序执行代码(例如汇编代码)的内存区域。这部分区域的地址范围和大小在程序运行前就已经确定。在进程或线程中被执行的函数的代码被存储在代码段段中,并且具有各自的地址范围。BSS段是用来存放程序中未初始化的全局变量的一块内存区域。数据段是用来存放程序中已初始化的全局变量的一块内存区域。BSS段和数据段属于静态内存分配。堆是用于存放进程或线程运行中被动态分配的内存段,它的大小并不固定,可以动态扩张或缩减。栈用于存储程序运行时和函数调用信息和临时创建的局部变量。
图4示出了根据本公开的实施例的线程的调用栈的示例示意图。在一些实施例中,调用栈400按照从高地址到低地址的方向可以包括用于存储命令行参数和环境变量的区域410和栈帧区420。
调用栈的最高地址的位置可以被称为栈底401,最低地址的位置可以被称为栈顶402。根据体系结构的不同,区域410可以具有不同的大小,例如,200个字节。在一些实施例中,CPU的中一个寄存器可以保存调用栈的栈顶402的栈地址,该寄存器可以被称为栈顶指针。
在区域410之后的栈帧区420中存储有线程的函数的栈帧。在线程的执行过程中,每当调用函数时,按照从高地址到低地址的方向,为被调用的函数分配栈帧。函数被调用时,根据被调用函数的代码,为该函数分配适当大小的栈帧。作为示例,该线程的栈帧区420包括作为根函数的A函数的栈帧422。当A函数调用B函数时,在A的栈帧422的下方,即更低的地址范围内,分配B函数的栈帧。类似地,当B函数进一步调用其他函数时,将在B函数的栈帧的下方,分配被调用函数的栈帧,以此类推,直到叶子函数的栈帧426。叶子函数是指未调用任何其他函数的函数。可以看出,当迭代地产生函数调用时,线程的调用栈400是从高地址向低地址生长的。也就是说,栈顶指针所存储的栈顶地址向下生长。待到调用结束后,调用栈中的栈帧也会被依次回收。因此,栈具有先进先出的特点,可以用于保存/恢复调用现场。
提供以下示例性代码,并结合图5来描述调用栈400的示例性布局。
Figure BDA0003209580440000071
上述示例性代码描述了在线程的执行过程中A函数调用B函数,B函数调用C函数的过程。图5示出了根据本公开的实施例的调用栈500的更详细的示意图。
在函数A被执行时,从调用栈500的高地址处分配A函数的栈帧510,并且根据操作系统的具体实现方式在栈帧中存储数据。在一些实施例中,栈帧514的大小可以A函数的代码中由编译器指定。例如,A函数的汇编代码的第一条代码可以指定栈帧大小,并且将调用栈500的栈顶指针修改为指向栈帧514的顶部。在本文中,栈帧的顶部地址也被称为该栈帧的栈地址(FP)。
如图所示,A函数的栈帧510包括A函数的局部变量区514,局部变量区514包括A函数中声明的变量int a_s3、int a_s2、int a_s1。根据操作系统的应用程序二进制接口(ABI),将在后声明的变量int a_s3压入调用栈500,然后压入int a_s2和int a_s1。栈帧514还包括514还包括参数传递区516。在一些实施例中,当调用B函数,例如执行到内存中的跳转指令时,调用参数1和2可以被压入调用栈500,根据ABI,在后的参数2被先压入调用栈500,然后压入参数1。参数传递区516中的参数1和2可以被函数B的代码访问。
在一些实施例中,跳转到B函数的代码时,在调用栈500中分配B函数的栈帧520。类似地,B函数的栈帧大小可以在A函数的汇编代码的第一条代码由编译器指定,相应地,栈顶指针更新为栈帧520的栈地址。在一些实施例中,由于B函数被A函数调用,所以首先在栈帧520中存储A函数的执行环境,即CPU的寄存器数据。如图所示,A函数的执行环境被存储在栈帧520的调用信息区522。
在一些实施例中,调用信息区522包括调用后的返回地址、调用函数的栈帧的栈地址和其他要保存的寄存器。返回地址可以来源于CPU的特定寄存器,该特定寄存器存储当前执行指令(例如,存储在PC寄存器中)的下一条指令的地址(例如,在ARM体系结构中,LR寄存器)。参照上述示例代码,调用B函数的下一条代码是“Printf(“A\n”)”,因此,存储在该特定寄存器中的Printf(“A\n”)的代码的地址被压入栈帧520。如上所述,栈顶指针寄存器存储调用栈500的栈顶地址。此时,调用栈500的栈顶地址等于栈帧510的栈地址。因此,通过将栈顶指针压入栈帧520,在调用信息区522存储了A函数的栈帧地址FP,如图中的箭头所示。此外,根据具体实现,可以将其他寄存器数据压入调用信息区522。
类似地,栈帧520还包括局部变量区524和参数传递区526。它们的内容和生成方式与A的栈帧510类似,在此不再赘述。
根据如上代码,B函数还调用了C函数。C函数的栈帧530的内容和生成方式与B函数的栈帧520类似,在此也不再赘述。需要注意的是,上述示例代码中的C函数未调用任何其他函数。因此在栈帧530包括调用信息区532和局部变量区534,不包含调用参数区526(以虚线表示)。
图6示出了根据本公开的实施例的用于获取函数调用信息的过程600的示意流程图。通过执行过程600,可以实现反向backtrace方法,获取函数调用信息。
在框610,从调用栈中获取第一调用返回地址,第一调用返回地址在第一函数(例如A函数)的代码的地址范围内。在一些实施例中,内存中的调用栈已经被转储,并且通过使用线程控制块来获取到调用栈的栈底地址。应理解,代码段存储了线程的所有函数的代码。因此,函数调用的返回地址在代码段的地址范围内。可以通过扫描调用栈来获取该第一调用返回地址,参考图7和图8描述。
图7示出了根据本公开的实施例的用于获取调用返回地址的过程700的示意流程图。图8示出了根据本公开的实施例的结合代码段来解析调用栈的示意图。
在框710,在调用栈810中查找在代码段820的地址范围内的第一地址。参照图8,调用栈810从高地址到低地址依次包括第一函数的栈帧802和第二函数的栈帧804。尽管图8未示出,调用栈810还可以包括更多的函数的栈帧。在一些实施例中,第一函数是调用栈810中的根函数,从根函数的栈帧802开始来查找在代码段的地址范围内的地址。根函数的栈帧802位于栈帧区的底部。
如上所述,在栈帧底部和栈帧区之间包括命令行和环境变量809。在一些实施例中,从相对于调用栈的栈底地址的预定偏移处801开始,从高地址到低地址在调用栈中查找在代码段的地址范围内的第一地址。由此,可以跨过命令行和环境变量809,从栈帧802的底部(即最高地址处)开始查找。栈底地址可以从线程控制块获取,因而可以从调用栈的栈底开始查找函数调用的返回地址,所以不需要CPU的寄存器数据。
当查找到位于代码段820的地址范围内的地址时,可以检查该地址是否为函数调用的返回地址。在框720,判断第一地址处的代码的上一条代码是否为跳转指令。如果上一条代码不是跳转指令,表明查找到的第一地址不是函数调用的返回地址,继续查找。
如果上一条代码是跳转指令,表明查找到的第一地址是函数调用的返回地址,则在框730,可以获取第一地址作为第一调用返回地址。作为示例,如图8所示,在调用栈810查找到的位于代码段820内的地址,该地址指向Printf(“A\n”)的汇编代码821。这时,可以对查找到地址进行偏移,例如,减4(即地址为4字节数据)以定位到上一个代码822。代码822为跳转到第二函数的代码,因此,在调用栈810中查找到的地址可以被确定为第一调用返回地址806。如果上一条代码不是跳转指令,则查找到的地址不是函数调用返回地址。
通过图7所示的方法700,以此方式,能够检验从调用栈获取的第一地址是否属于函数调用的返回地址,从而提高了可靠性和健壮性。
继续参考图6,在框620,基于第一调用返回地址806,在第一函数的代码中确定第一调用代码822,该第一调用代码822指示由第一函数调用第二函数。在一些实施例中,可以将返回地址处的代码的上一条代码确定为第一函数调用第二函数的代码822。
在框630,从第一调用代码822获取第二函数的代码的起始地址。第一调用代码822包括第二函数的起始代码在代码段中的存储地址。通过解析第一函数调用第二函数的代码可以获取被调函数的代码的起始地址。由此,可以确定第一函数调用第二函数的函数调用信息。
在一些实施例中,可以使用第一调用返回地址从符号表获取第一函数的标识,并且使用所述第二函数的代码的起始地址从符号表830获取第二函数的标识。符号表830是由编译器生成的,包括程序源代码中的每个标识符和相关联的信息,例如数据类型、作用域以及内存地址。可以使用第一调用返回地址806从符合表830查询到第一函数的标识及其代码的内存地址范围,这是因为第一调用返回地址在第一函数的代码的地址范围内。同样,也可以使用第二函数的代码的起始地址从获取第二函数的标识及其代码的内存地址范围。
在一些实施例中,可以呈现第一函数的标识、第二函数的标识以及第一函数调用第二函数的代码的存储地址。由此,可以帮助定位程序出错的原因。
在一些实施例中,还可以迭代地解析调用栈810以获取进一步的函数调用信息。为此,需要确定第二函数是否进一步调用了第三函数,即,确定第二函数是否为叶子函数。
图9示出了根据本公开的实施例的用于确定函数是否为叶子函数的过程900的示意流程图。如图8所示,调用栈810包括第一函数的栈帧802和第二函数的栈帧804,第二函数的栈帧804包括第一调用返回地址806和第一栈帧的栈地址808。应理解,根据函数调用的压栈过程,如果第二函数调用了其他函数,例如第三函数,则在第三函数的栈帧的信息区中存储有第二函数调用第三函数的返回地址816,并且存储有第二函数的栈帧804的栈地址818,其中返回地址816在第二函数的代码段的地址范围内。在这种情况下,取决于操作系统的具体实现,在第二栈帧804后的第三栈帧814中特定位置处存储有上述信息。
在框910,确定相对于第二栈帧804的栈地址的第一栈地址处是否存在位于第二函数的代码的地址范围内的第二地址。例如,取决于操作系统的具体实现,可以在紧邻着第二栈帧804,即,第三函数的栈帧814的前4个字节存储第二地址。在一些实施例中,也可以在相对于第二栈帧804的栈地址的其他偏移位置处,例如,在第二栈帧804的栈地址之后第5至8个字节存储该第二地址,本公开对此不做限制。
如果在第一栈地址处不存在这样的第二地址,则表明第二栈帧804之后没有其他函数的栈帧,即,第二函数没有调用第三函数,是叶子函数,因此不需要继续解析调用栈。如果存在这样的第二地址,在框920,确定在相对于第二栈帧804的栈地址的的第二栈地址处是否存在第二栈帧的栈地址。例如,取决于操作系统的具体实现,可以在第二栈帧804之后的第5至8个字节存储第二栈帧804的栈地址。在一些实施例中,也可以在相对于第二栈帧804的栈地址的其他偏移处存储第二栈帧804的栈地址,例如,在第二栈帧804的栈地址之后第1至4个字节存储第二栈帧804的栈地址,本公开对此不做限制。
如果在该第二栈地址处不存在这样的栈地址,则表明第二函数没有调用第三函数,是叶子函数,不需要继续解析调用栈。如果存在这样的栈地址,进一步地,在框930,确定第二地址处的代码的上一条代码是否为跳转指令。该步骤与框720描述的操作类似,不再赘述。
如果该上一条代码不是跳转指令,表明第二地址不是函数调用的返回地址,第二函数是叶子函数,不需要继续解析调用栈。如果上一条代码是跳转指令,表明查找到的第二地址是函数调用的返回地址,则在框940,确定第二函数调用第三函数,并且获取第二地址作为第二调用返回地址。
图10示出了根据本公开的实施例的用于进一步获取函数调用信息的过程1000的示意流程图。响应于被调用的函数(例如第二函数)进一步调用其他函数(例如第三函数),进一步迭代地解析调用栈。
在框1010,基于第二栈帧804的栈地址,从第三函数的第三栈帧814中获取第二调用返回地址816,第二调用返回地址在第二函数的代码的地址范围内。
在一些实施例中,第二栈帧804的栈地址可以通过从第一栈帧802的栈地址减去第二栈帧的大小来得到第二栈帧804的栈地址。参考图8,第一返回调用地址806和第一栈帧的栈地址是相邻存储的,或者根据操作系统的具体实现而相隔预定偏移。因此,可以基于调用栈中存储第一调用返回地址806的栈地址,从第二栈帧804获取第一栈帧的栈地址808。另外,第二栈帧804的大小可以基于第二函数的代码来确定。具体地,使用在框630已经获取的第二函数的代码的起始地址,从符号表830获取到第二函数的代码的地址范围。在一些实施例中,在代码段中的函数的起始代码包括栈帧分配代码,栈帧分配代码包括栈帧大小。由此,可以基于第二函数的代码的起始地址,获取第二栈帧804的大小。由此,通过从第一栈帧的栈地址减去第二栈帧的大小来得到第二栈帧的栈地址。
参考图8,根据第二栈帧的栈地址,就能访问到第三栈帧的调用信息区,包括第三函数被第二函数调用后的返回地址,即第二调用返回地址816,以及第二栈帧的栈地址818。
与方法600的框620类似,在框1020,基于第二调用返回地址,在第二函数的代码中确定由第二函数调用第三函数的代码。
与方法600的框630类似,在框1030,从调用第三函数的代码获取第三函数的代码的起始地址。由此,通过解析调用栈,进一步获取了第二函数调用第三函数的调用信息。
然后,在框1040,确定第三函数是否是叶子函数。确定第三函数是为叶子函数的方式与参考图9描述的方法类似,在此不再赘述。
如果确定第三函数是叶子函数,则在框1050,完成解析得到函数调用信息。如果确定第三函数不是叶子函数,即,调用了第四函数,则方法1000可以被迭代地执行,直到解析到没有进一步的函数调用为止。
在一些实施例中,可以使用解析得到的函数的代码的地址,从符号表获取这些函数的标识。在一些实施例中,还可以通过调用返回地址来获取到发生调用的位置、以及所有函数的代码段的地址和大小等信息。通过向用户呈现这些信息,可以帮助定位程序出错的位置和原因。
以上参考图3至图10描述了根据本公开的实施例的获取函数调用信息的方法。相比于以CPU核的寄存器数据作为入口数据来获取函数调用信息的传统方法,本公开提供的方法不需要CPU核的寄存器数据就能够获取函数调用信息,因此适用于在CPU核挂死而无法访问寄存器数据的情况下定位程序出错的原因。
图11示出了根据本公开的实施例的用于获取函数调用信息的装置1100的示意框图。装置1100包括第一调用返回地址获取单元1110、调用代码确定单元1120和被调函数代码地址获取单元1130。
第一调用返回地址获取单元1110被配置用于从调用栈中获取第一调用返回地址,第一调用返回地址在第一函数的代码的地址范围内。调用代码确定单元1120被配置用于基于第一调用返回地址在第一函数的代码中确定第一调用代码,第一调用代码指示由第一函数调用第二函数。被调函数代码地址获取单元1130被配置用于从第一调用代码中获取第二函数的代码的起始地址。
在一些实施例中,第一调用返回地址获取单元1110还可以被配置用于:在调用栈中查找在代码段的地址范围内的第一地址,该代码段包括第一函数和第二函数的代码;确定第一地址处的代码的上一条代码是否为跳转指令;以及当确定该上一条代码为跳转指令时,获取该第一地址作为第一调用返回地址。
在一些实施例中,第一调用返回地址获取单元1110还可以被配置用于:从相对于调用栈的栈底地址的预定偏移处开始,从高地址到低地址在调用栈中查找在代码段的地址范围内的第一地址。
在一些实施例中,调用栈包括第一函数的第一栈帧和第二函数的第二栈帧,第二栈帧包括相邻存储的第一调用返回地址和第一栈帧的栈地址。装置1100还可以包括函数调用确定单元,该函数调用单元被配置用于确定第二函数是否调用了第三函数。该装置还可以包括第二调用地址返回单元,该第二调用地址返回单元被配置用于当确定第二函数调用了第三函数时,基于第二栈帧的栈地址,从第三函数的第三栈帧中获取第二调用返回地址,第二调用返回地址在第二函数的代码的地址范围内;基于第二调用返回地址,在第二函数的代码中确定第二调用代码,第二调用代码指示由第二函数调用第三函数;以及从第二调用代码获取所述第三函数的代码的起始地址。
在一些实施例中,函数调用确定单元还可以被配置用于:确定在相对于所述第二栈帧的栈地址的第一栈地址处是否存在位于第二函数的代码的地址范围内的第二地址、并且在相对于所述第二栈帧的栈地址的第二栈帧地址处是否存在第二栈帧的栈地址;如果第一栈地址处存在该第二地址并且第二栈地址处存在第二栈帧的栈地址,确定该第二地址处的代码的上一条代码是否为跳转指令;以及如果该上一条代码为跳转指令,确定第二函数调用了第三函数并且获取第二地址作为第二调用返回地址。
在一些实施例中,装置1100还可以包括栈帧地址确定单元。栈帧地址确定单元可以被配置用于:基于调用栈中存储的第一调用返回地址的栈地址,从第二栈帧中获取第一栈帧的栈地址;基于第二函数的代码的起始地址,获取第二栈帧的大小;以及基于第一栈帧的栈地址和第二栈帧的大小,确定第二栈帧的栈地址。
在一些实施例中,装置1100还可以包括函数标识确定单元,函数标识确定单元可以被配置用于:使用第一调用返回地址从符号表获取第一函数的标识;以及使用第二函数的代码的起始地址从符号表获取第二函数的标识。
在一些实施例中,装置1100还可以包括呈现单元,呈现单元可以被配置用于呈现以下至少一项:第一函数的标识,第二函数的标识,以及指示第一函数调用第二函数的第一调用代码的存储地址。
图12示出了可以用来实施本公开的实施例的示例设备1200的示意性框图。设备1200可以用于实现如图3、图6、图7、图9、图10所示的过程以及如图11所示的装置。如图所示,设备1200包括中央处理单元(CPU)1201,中央处理单元1201可以包括多个核,每个核可以根据存储在只读存储器(ROM)1202中的计算机程序指令或者从存储单元1208加载到随机访问存储器(RAM)1203中的计算机程序指令,来执行各种适当的动作和处理。在RAM 1203中,还可存储设备1200操作所需的各种程序和数据。CPU 1201、ROM 1202以及RAM 1203通过总线1204彼此相连。输入/输出(I/O)接口1205也连接至总线1204。
设备1200中的多个部件连接至I/O接口1205,包括:输入单元1206,例如键盘、鼠标等;输出单元1207,例如各种类型的显示器、扬声器等;存储单元1208,例如磁盘、光盘等;以及通信单元1209,例如网卡、调制解调器、无线通信收发机等。通信单元1209允许设备1200通过诸如因特网的计算机网络和/或各种电信网络与其他设备交换信息/数据。
上文所描述的各个过程和处理,例如方法300、600、700、900、1000可由处理单元1201中的一个或多个核来执行。例如,在一些实施例中,方法300、600、700、900、1000可被实现为计算机软件程序,其被有形地包含于机器可读介质,例如存储单元1208。在一些实施例中,计算机程序的部分或者全部可以经由ROM 1202和/或通信单元1209而被载入和/或安装到设备1200上。当计算机程序被加载到RAM 1203并由CPU 1201或CPU的核执行时,可以执行上文描述的方法300、600、700、900、1000的一个或多个动作。
本公开可以是方法、装置、系统和/或计算机程序产品。计算机程序产品可以包括计算机可读存储介质,其上载有用于执行本公开的各个方面的计算机可读程序指令。
计算机可读存储介质可以是可以保持和存储由指令执行设备使用的指令的有形设备。计算机可读存储介质例如可以是――但不限于――电存储设备、磁存储设备、光存储设备、电磁存储设备、半导体存储设备或者上述的任意合适的组合。计算机可读存储介质的更具体的例子(非穷举的列表)包括:便携式计算机盘、硬盘、随机存取存储器(RAM)、只读存储器(ROM)、可擦式可编程只读存储器(EPROM或闪存)、静态随机存取存储器(SRAM)、便携式压缩盘只读存储器(CD-ROM)、数字多功能盘(DVD)、记忆棒、软盘、机械编码设备、例如其上存储有指令的打孔卡或凹槽内凸起结构、以及上述的任意合适的组合。这里所使用的计算机可读存储介质不被解释为瞬时信号本身,诸如无线电波或者其他自由传播的电磁波、通过波导或其他传输媒介传播的电磁波(例如,通过光纤电缆的光脉冲)、或者通过电线传输的电信号。
这里所描述的计算机可读程序指令可以从计算机可读存储介质下载到各个计算/处理设备,或者通过网络、例如因特网、局域网、广域网和/或无线网下载到外部计算机或外部存储设备。网络可以包括铜传输电缆、光纤传输、无线传输、路由器、防火墙、交换机、网关计算机和/或边缘服务器。每个计算/处理设备中的网络适配卡或者网络接口从网络接收计算机可读程序指令,并转发该计算机可读程序指令,以供存储在各个计算/处理设备中的计算机可读存储介质中。
用于执行本公开操作的计算机程序指令可以是汇编指令、指令集架构(ISA)指令、机器指令、机器相关指令、微代码、固件指令、状态设置数据、或者以一种或多种编程语言的任意组合编写的源代码或目标代码,编程语言包括面向对象的编程语言—诸如Smalltalk、C++等,以及常规的过程式编程语言—诸如“C”语言或类似的编程语言。计算机可读程序指令可以完全地在用户计算机上执行、部分地在用户计算机上执行、作为一个独立的软件包执行、部分在用户计算机上部分在远程计算机上执行、或者完全在远程计算机或服务器上执行。在涉及远程计算机的情形中,远程计算机可以通过任意种类的网络—包括局域网(LAN)或广域网(WAN)—连接到用户计算机,或者,可以连接到外部计算机(例如利用因特网服务提供商来通过因特网连接)。在一些实施例中,通过利用计算机可读程序指令的状态信息来个性化定制电子电路,例如可编程逻辑电路、现场可编程门阵列(FPGA)或可编程逻辑阵列(PLA),该电子电路可以执行计算机可读程序指令,从而实现本公开的各个方面。
这里参照根据本公开实施例的方法、装置(系统)和计算机程序产品的流程图和/或框图描述了本公开的各个方面。应当理解,流程图和/或框图的每个方框以及流程图和/或框图中各方框的组合,都可以由计算机可读程序指令实现。
这些计算机可读程序指令可以提供给通用计算机、专用计算机或其它可编程数据处理装置的处理单元,从而生产出一种机器,使得这些指令在通过计算机或其它可编程数据处理装置的处理单元执行时,产生了实现流程图和/或框图中的一个或多个方框中规定的功能/动作的装置。也可以把这些计算机可读程序指令存储在计算机可读存储介质中,这些指令使得计算机、可编程数据处理装置和/或其他设备以特定方式工作,从而,存储有指令的计算机可读介质则包括一个制造品,其包括实现流程图和/或框图中的一个或多个方框中规定的功能/动作的各个方面的指令。
也可以把计算机可读程序指令加载到计算机、其它可编程数据处理装置、或其它设备上,使得在计算机、其它可编程数据处理装置或其它设备上执行一系列操作步骤,以产生计算机实现的过程,从而使得在计算机、其它可编程数据处理装置、或其它设备上执行的指令实现流程图和/或框图中的一个或多个方框中规定的功能/动作。
附图中的流程图和框图显示了根据本公开的多个实施例的系统、方法和计算机程序产品的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段或指令的一部分,模块、程序段或指令的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。在有些作为替换的实现中,方框中所标注的功能也可以以不同于附图中所标注的顺序发生。例如,两个连续的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或动作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。
以上已经描述了本公开的各实施方式,上述说明是示例性的,并非穷尽性的,并且也不限于所披露的各实施方式。在不偏离所说明的各实施方式的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。本文中所用术语的选择,旨在最好地解释各实施方式的原理、实际应用或对市场中的技术的改进,或者使本技术领域的其他普通技术人员能理解本文披露的各实施方式。

Claims (19)

1.一种用于获取函数调用信息的方法,包括:
从调用栈中获取第一调用返回地址,所述第一调用返回地址在第一函数的代码的地址范围内;
基于所述第一调用返回地址,在所述第一函数的代码中确定第一调用代码,所述第一调用代码指示由所述第一函数调用第二函数;以及
从所述第一调用代码中获取所述第二函数的代码的起始地址。
2.根据权利要求1所述的方法,其中从所述调用栈中获取所述第一调用返回地址包括:
在所述调用栈中查找在代码段的地址范围内的第一地址,所述代码段包括所述第一函数和所述第二函数的代码;
确定所述第一地址处的代码的上一条代码是否为跳转指令;以及
当所述上一条代码为跳转指令时,获取所述第一地址作为所述第一调用返回地址。
3.根据权利要求2所述的方法,其中在所述调用栈中查找在代码段的地址范围内的第一地址包括:
从相对于所述调用栈的栈底地址的预定偏移处开始,从高地址到低地址在所述调用栈中查找在所述代码段的地址范围内的所述第一地址。
4.根据权利要求1所述的方法,其中所述调用栈包括所述第一函数的第一栈帧和所述第二函数的第二栈帧,所述第二栈帧包括相邻存储的所述第一调用返回地址和所述第一栈帧的栈地址,所述方法还包括:
确定所述第二函数是否调用了第三函数;以及
当确定所述第二函数调用了所述第三函数时,
基于所述第二栈帧的栈地址,从所述第三函数的第三栈帧中获取所述第二调用返回地址,所述第二调用返回地址在所述第二函数的代码的地址范围内;
基于所述第二调用返回地址,在所述第二函数的代码中确定第二调用代码,所述第二调用代码指示由所述第二函数调用所述第三函数;以及
从所述第二调用代码中获取所述第三函数的代码的起始地址。
5.根据权利要求4所述的方法,其中确定所述第二函数确定是否调用了第三函数包括:
确定相对于所述第二栈帧的栈地址的第一栈地址处是否存在位于所述第二函数的代码的地址范围内的第二地址并且在相对于所述第二栈帧的栈地址的的第二栈地址处是否存在所述第二栈帧的栈地址;
如果在所述第一栈地址处存在所述第二地址并且在所述第二栈地址处存在所述第二栈帧的栈地址,确定所述第二地址处的代码的上一条代码是否为跳转指令;以及
如果所述上一条代码为跳转指令,确定所述第二函数调用了所述第三函数,并且获取所述第二地址作为所述第二调用返回地址。
6.根据权利要求4所述的方法,还包括:
基于所述调用栈中存储的所述第一调用返回地址的栈地址,从所述第二栈帧中获取所述第一栈帧的栈地址;
基于所述第二函数的代码的起始地址,获取所述第二栈帧的大小;以及
基于所述第一栈帧的栈地址和所述第二栈帧的大小,确定所述第二栈帧的栈地址。
7.根据权利要求1所述的方法,还包括:
使用所述第一调用返回地址从符号表获取所述第一函数的标识;以及
使用所述第二函数的代码的起始地址从所述符号表获取所述第二函数的标识。
8.根据权利要求6所述的方法,还包括:呈现以下至少一项:
所述第一函数的标识,
所述第二函数的标识,以及
指示所述第一函数调用所述第二函数的所述第一调用代码的存储地址。
9.一种用于获取函数调用信息的装置,包括:
第一调用返回地址获取单元,被配置用于从调用栈中获取第一调用返回地址,所述第一调用返回地址在第一函数的代码的地址范围内;
调用代码确定单元,被配置用于基于所述第一调用返回地址在所述第一函数的代码中确定第一调用代码,所述第一调用代码指示由所述第一函数调用第二函数;以及
被调函数代码地址获取单元,被配置用于从所述第一调用代码中获取所述第二函数的代码的起始地址。
10.根据权利要求9所述的装置,其中所述第一调用返回地址获取单元被配置用于:
在所述调用栈中查找在代码段的地址范围内的第一地址,所述代码段包括所述第一函数和所述第二函数的代码;
确定所述第一地址处的代码的上一条代码是否为跳转指令;以及
当确定所述上一条代码为跳转指令时,获取所述第一地址作为所述第一调用返回地址。
11.根据权利要求9所述的装置,其中所述第一调用返回地址获取单元还被配置用于:
从相对于所述调用栈的栈底地址的预定偏移处开始,从高地址到低地址在所述调用栈中查找在所述代码段的地址范围内的所述第一地址。
12.根据权利要求9所述的装置,其中所述调用栈包括所述第一函数的第一栈帧和所述第二函数的第二栈帧,所述第二栈帧包括相邻存储的所述第一调用返回地址和所述第一栈帧的栈地址,所述装置还包括:
函数调用确定单元,被配置用于确定所述第二函数是否调用了第三函数;以及
第二调用地址返回单元,被配置用于当确定所述第二函数调用了所述第三函数时,
基于所述第二栈帧的栈地址,从所述第三函数的第三栈帧中获取所述第二调用返回地址,所述第二调用返回地址在所述第二函数的代码的地址范围内;
基于所述第二调用返回地址,在所述第二函数的代码中确定第二调用代码,所述第二调用代码指示由所述第二函数调用所述第三函数;以及
从所述第二调用代码中获取所述第三函数的代码的起始地址。
13.根据权利要求12所述的装置,其中函数调用确定单元还被配置用于:
确定相对于所述第二栈帧的栈地址的第一栈地址处是否存在位于所述第二函数的代码的地址范围内的第二地址并且在相对于所述第二栈帧的栈地址的第二栈帧地址处是否存在所述第二栈帧的栈地址;
如果在所述第一栈地址处存在所述第二地址并且在所述第二栈地址处存在所述第二栈帧的栈地址,确定所述第二地址处的代码的上一条代码是否为跳转指令;以及
如果所述上一条代码为跳转指令,确定所述第二函数调用了所述第三函数并且获取所述第二地址作为所述第二调用返回地址。
14.根据权利要求12所述的装置,还包括栈帧地址确定单元,所述栈帧地址确定单元被配置用于:
基于所述调用栈中存储的所述第一调用返回地址的栈地址,从所述第二栈帧中获取所述第一栈帧的栈地址;
基于所述第二函数的代码的起始地址,获取所述第二栈帧的大小;以及
基于所述第一栈帧的栈地址和所述第二栈帧的大小,确定所述第二栈帧的栈地址。
15.根据权利要求9所述的装置,还包括函数标识确定单元,所述函数标识确定单元被配置用于:
使用所述第一调用返回地址从符号表获取所述第一函数的标识;以及
使用所述第二函数的代码的起始地址从所述符号表获取所述第二函数的标识。
16.根据权利要求15所述的装置,还包括呈现单元,所述呈现单元被配置用于呈现以下至少一项:
所述第一函数的标识,
所述第二函数的标识,以及
指示所述第一函数调用所述第二函数的所述第一调用代码的存储地址。
17.一种电子设备,包括
处理器,所述处理器包括多个处理核;以及
存储器;
所述多个处理核中的至少一个处理核被配置用于执行所述存储器中的指令,使得所述电子设备执行根据权利要求1至8中任一项所述的方法。
18.一种计算机可读存储介质,其上存储有一条或多条计算机指令,其中一条或多条计算机指令被处理器执行使所述处理器执行根据权利要求1至8中任一项所述的方法。
19.一种计算机程序产品,包括机器可执行指令,所述机器可执行指令在由设备执行时使所述设备执行根据权利要求1至8中任一项所述的方法。
CN202110926882.4A 2021-08-12 2021-08-12 用于获取函数调用信息的方法、装置、电子设备和介质 Active CN115705294B (zh)

Priority Applications (2)

Application Number Priority Date Filing Date Title
CN202110926882.4A CN115705294B (zh) 2021-08-12 2021-08-12 用于获取函数调用信息的方法、装置、电子设备和介质
PCT/CN2022/111410 WO2023016485A1 (zh) 2021-08-12 2022-08-10 用于获取函数调用信息的方法、装置、电子设备和介质

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN202110926882.4A CN115705294B (zh) 2021-08-12 2021-08-12 用于获取函数调用信息的方法、装置、电子设备和介质

Publications (2)

Publication Number Publication Date
CN115705294A true CN115705294A (zh) 2023-02-17
CN115705294B CN115705294B (zh) 2024-07-05

Family

ID=85181018

Family Applications (1)

Application Number Title Priority Date Filing Date
CN202110926882.4A Active CN115705294B (zh) 2021-08-12 2021-08-12 用于获取函数调用信息的方法、装置、电子设备和介质

Country Status (2)

Country Link
CN (1) CN115705294B (zh)
WO (1) WO2023016485A1 (zh)

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN117171058B (zh) * 2023-11-03 2024-02-20 睿思芯科(深圳)技术有限公司 调用链实时追踪方法、系统及相关设备

Citations (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101261603A (zh) * 2008-04-09 2008-09-10 中兴通讯股份有限公司 故障定位的方法和装置
CN103019787A (zh) * 2012-12-14 2013-04-03 华为技术有限公司 函数调用关系确定方法、热补丁升级方法及装置
CN105468965A (zh) * 2014-08-21 2016-04-06 西安慧泽知识产权运营管理有限公司 一种动态堆栈内存管理方法
CN106933733A (zh) * 2015-12-30 2017-07-07 华为技术有限公司 一种确定内存泄露位置的方法和装置
US20200371945A1 (en) * 2019-05-22 2020-11-26 Vdoo Connected Trust Ltd. Dynamic Identification of Stack Frames
CN112740187A (zh) * 2018-10-09 2021-04-30 华为技术有限公司 调试程序的方法和系统

Family Cites Families (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7574702B2 (en) * 2005-03-18 2009-08-11 Microsoft Corporation Method and apparatus for hybrid stack walking
CN101539883B (zh) * 2009-05-05 2011-11-16 北京和利时系统工程有限公司 嵌入式系统的错误追踪方法和装置
CN102109975B (zh) * 2009-12-24 2015-03-11 华为技术有限公司 确定函数调用关系的方法、装置及系统
US8850408B2 (en) * 2011-08-10 2014-09-30 Nintendo Of America, Inc. Methods and/or systems for determining a series of return callstacks
CN103019707B (zh) * 2012-11-30 2016-01-27 华为技术有限公司 调用栈的解析处理方法及装置
CN103559123B (zh) * 2013-10-24 2016-02-10 烽火通信科技股份有限公司 基于VxWorks操作系统的函数调用栈分析方法及装置

Patent Citations (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN101261603A (zh) * 2008-04-09 2008-09-10 中兴通讯股份有限公司 故障定位的方法和装置
CN103019787A (zh) * 2012-12-14 2013-04-03 华为技术有限公司 函数调用关系确定方法、热补丁升级方法及装置
CN105468965A (zh) * 2014-08-21 2016-04-06 西安慧泽知识产权运营管理有限公司 一种动态堆栈内存管理方法
CN106933733A (zh) * 2015-12-30 2017-07-07 华为技术有限公司 一种确定内存泄露位置的方法和装置
CN112740187A (zh) * 2018-10-09 2021-04-30 华为技术有限公司 调试程序的方法和系统
US20200371945A1 (en) * 2019-05-22 2020-11-26 Vdoo Connected Trust Ltd. Dynamic Identification of Stack Frames

Also Published As

Publication number Publication date
WO2023016485A1 (zh) 2023-02-16
CN115705294B (zh) 2024-07-05

Similar Documents

Publication Publication Date Title
CN111090536B (zh) 一种获取内存泄露信息的方法、装置、介质和电子设备
JP7090657B2 (ja) アプリケーションをアップグレードするための方法、装置、デバイスならびに記憶媒体
US8719791B1 (en) Display of aggregated stack traces in a source code viewer
US8141059B2 (en) Method and system for avoidance of software conflict
KR100868762B1 (ko) 임베디드용 소프트웨어의 오류 검출 방법
US10339031B2 (en) Efficient method data recording
CN110213207B (zh) 一种基于日志分析的网络安全防御方法及设备
US20100095278A1 (en) Tracing a calltree of a specified root method
US20050204342A1 (en) Method, system and article for detecting memory leaks in Java software
CN110489310B (zh) 一种记录用户操作的方法、装置、存储介质及计算机设备
US8930970B2 (en) Method and computer for obtaining using-frequency of application program
CN113760306A (zh) 安装软件的方法、装置、电子设备及存储介质
WO2023016485A1 (zh) 用于获取函数调用信息的方法、装置、电子设备和介质
CN113176926A (zh) 一种基于虚拟机自省技术的api动态监控方法及系统
CN110297639B (zh) 用于检测代码的方法和装置
US12093686B2 (en) Code maintenance system
CN111352631A (zh) 一种接口兼容性检测方法及装置
US8819494B2 (en) Automatically changing parts in response to tests
US6732355B1 (en) Method and device for generating registration data at compilation to enable trace of stack
CN116051031A (zh) 项目调度系统、介质及电子设备
CN111475226B (zh) 电子装置、微服务调用方法和计算机可读存储介质
CN112860235B (zh) 处理文本的方法、装置、设备和存储介质
CN114721709A (zh) 程序包生成方法、装置、存储介质及计算机设备
CN112783574A (zh) 应用程序开发方法、装置、设备和存储介质
US20230401069A1 (en) Exception handling method and related apparatus

Legal Events

Date Code Title Description
PB01 Publication
PB01 Publication
SE01 Entry into force of request for substantive examination
SE01 Entry into force of request for substantive examination
GR01 Patent grant
GR01 Patent grant