Stack trace using shadow stack

By synchronizing the return address between the call stack and the shadow stack, the problem of high computational overhead of existing stack backtrace tracing methods is solved, and low-overhead, efficient stack backtrace tracing and security enhancement are achieved, which is suitable for various computing devices and systems.

CN114144764BActive Publication Date: 2025-10-10MICROSOFT TECHNOLOGY LICENSING LLC
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202080037709.2
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Priority Date
2019-05-20
Filing Date
2020-04-10
Publication Date
2025-10-10
Estimated Expiration
2040-04-10

AI Technical Summary

Technical Problem

Existing stack backtrace tracing methods incur excessive computational overhead in production systems and user devices, impacting system performance and making them vulnerable to malicious code attacks.

Method used

The shadow stack is used to synchronize with the call stack. By adding and removing return addresses to the shadow stack when a function is called and exited, a call chain backtrace of the program is generated, reducing computational overhead and enhancing security.

Benefits of technology

This implements low-overhead, efficient stack backtrace tracing, reduces system latency, and improves system security, enabling remedial measures to be taken when stack frame corruption is detected.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN114144764B_ABST
    Figure CN114144764B_ABST
Patent Text Reader

Abstract

A program is executed using a call stack and a shadow stack. The call stack includes frames with respective return addresses. The frames can also store variables and / or parameters. The shadow stack stores copies of the return addresses in the call stack. The call stack and the shadow stack are maintained by (i) adding a respective stack frame to the call stack and a respective return address to the shadow stack each time a function is called, and (ii) removing a respective frame from the call stack and a respective return address from the shadow stack each time a function is exited. A backtrace of the current call chain of the program is generated by accessing the return addresses in the shadow stack. The output backtrace includes return addresses from the shadow stack and / or information about traced functions derived from the return addresses of the shadow stack.
Need to check novelty before this filing date? Find Prior Art

Description

Background Art

[0001] Most programming languages ​​support modular construction and execution of software. Typically, a program has executable code modules or units, such as methods, subroutines, functions, etc. (collectively referred to herein as "functions"). A compiled program usually includes many such functions, each of which has a name or handle by which the function can be referenced. A function will have executable instructions and usually has parameters for exchanging data and locally declared variables for internal calculations. A program can be composed of many such functions, and in many cases, functions call other functions, such as a() calling b(), which then calls c(). An executed program may have a very long chain of such function calls.

[0002] To manage function calls and execution, most compilers compile programs to use some form of call stack during execution. Whenever a function is called (for example, a() calls b()), a new stack frame is pushed onto the call stack (in this case, b()'s frame is pushed on top of a()'s frame). The new frame contains the return address, which is the point in the program where the corresponding function was called (in this case, the point in a() where b() was called). Whenever a function exits, the function's frame is popped from the call stack, and control flow is transferred to any return addresses in the frame. Frames can also be used to store parameters passed to and from the function and local data declared within the function.

[0003] At any given time, the order of frames on the call stack reflects the current order of chained function calls, where each frame represents a function that has not yet exited. As a program executes, it is often desirable to know the current chain of function calls. This information (sometimes called a stack trace or backtrace) is very useful in debugging and performance analysis. As discussed below, there are different ways to construct a backtrace using the call stack, but all existing backtrace methods incur computational overhead, making backtrace impractical in some cases. For example, in many production systems and user devices, even a slight increase in latency can make backtrace unacceptable.

[0004] One existing method for backtracing involves saving the caller's frame address in the callee's stack frame and using a dedicated register (such as the x86 EBP register) to point to the current callee's frame. The dedicated register is used to retrieve the current stack frame, obtain the caller's stack frame address from the current stack frame, and obtain the caller's stack frame address from the current stack frame. In each frame, the return address of the corresponding function is stored at a fixed offset. Therefore, to obtain a stack backtrace, the return address of each frame must be found and transferred.

[0005] Another approach involves not saving the caller's stack frame address in the callee's stack frame. Instead, the stack frame size is calculated by executing the function prologue in reverse. Stack backtracing begins by calculating the stack size, then subtracting the stack size from the stack pointer to obtain the return address. Using the return address, the caller's stack frame size can be calculated, thus obtaining the caller's return address, and so on. Compared to the first approach, this approach is more efficient when no backtracing is performed (lower support overhead), but less efficient when stack backtracing is performed.

[0006] Another approach is to use special hardware support, such as Intel's Last Branch Recording (LBR). If LBR is configured in call stack mode, it will record active calls. This active call information can be dumped as a stack backtrace.

[0007] While these existing methods can produce the desired output, the overhead incurred is non-negligible. The first method requires additional instructions to save the caller's stack frame address in the callee's stack frame, and the caller's frame address must be calculated when "walking the stack." The second method requires a large number of memory lookups to find the frame size information. The third method emphasizes thread context switches because each context switch requires saving and restoring many additional registers.

[0008] Discussed below are techniques for using shadow stacks to facilitate backtracing with negligible overhead. Summary of the Invention

[0009] The following summary is intended only to introduce some of the concepts discussed in the detailed description below. This summary is not comprehensive and is not intended to delineate the scope of the claimed subject matter, which is set forth by the claims at the end.

[0010] A program is executed using a call stack and a shadow stack. The call stack includes frames with their own return addresses. These frames can also store variables and / or parameters. The shadow stack stores a copy of the return address in the call stack. The call stack and shadow stack are maintained in the following manner: (i) whenever a function is called, the corresponding stack frame is added to the call stack and the corresponding return address is added to the shadow stack, and (ii) whenever a function is exited, the corresponding frame is removed from the call stack and the corresponding return address is removed from the shadow stack. By accessing the return address in the shadow stack, a backtrace of the current call chain of the program is generated. The output backtrace includes the return address from the shadow stack and / or information about the traced function derived from the return address of the shadow stack.

[0011] Many of the attendant features will now be explained in conjunction with the following detailed description, which will be considered with reference to the accompanying drawings. BRIEF DESCRIPTION OF THE DRAWINGS

[0012] The description will be better understood from the following detailed description read in light of the accompanying drawings, wherein like elements are referred to by like reference characters, and in which:

[0013] Figure 1 An example of an executing program, and corresponding call stack and shadow stack, is shown.

[0014] Figure 2 An example of source code from which a compiler generates an executable program is shown.

[0015] Figure 3 Details of a call stack and shadow stack are shown.

[0016] Figure 4 How a call stack and shadow stack are maintained is shown.

[0017] Figure 5 A software-based implementation of a shadow stack is shown.

[0018] Figure 6 A hardware-based implementation of a shadow stack is shown.

[0019] Figure 7 How a shadow stack is used to satisfy a backtrace request is shown.

[0020] Figure 8 A process using a shadow stack is shown.

[0021] Figure 9 Using the contents of a shadow stack in combination with other information to generate a backtrace is shown.

[0022] Figure 10 Various contexts in which backtrace logic can be implemented are shown.

[0023] Figure 11 Examples of backtrace output are shown.

[0024] Figure 12 Details of a computing device are shown. DETAILED DESCRIPTION

[0025] Embodiments discussed below relate to using a shadow stack to enable efficient stack backtracing. An overview of call stacks and shadow stacks is first provided. Various ways of implementing a shadow stack are then described, followed by details of methods of using a shadow stack to facilitate stack backtracing.

[0026] Figure 11. The execution of a program 100 and the corresponding call stack 102 and shadow stack 104 are shown. The program 100 can be compiled machine instructions, bytecode, source code executed by an interpreter, etc. The program 100 includes various functions and calls to these functions. The call stack 102 can be implemented in any of a variety of known ways. As mentioned in the background, frames are pushed and popped based on function calls and exits / returns, respectively.

[0027] Shadow stack 104 can also be implemented in a known manner using software, hardware, or both. As mentioned in the background, in almost all call stack implementations, when a function exits, its stack frame is popped off the call stack, and execution control is transferred to whatever code location the frame's return address points to, typically a location within the function that called the exited function. The role of the call stack in flow control (i.e., providing the return address) is a well-known security vulnerability. By using various techniques, the call stack can be altered or corrupted to change the return address, thereby causing execution to point to the location of malicious code.

[0028] The shadow stack is a solution to return address vulnerabilities. Simply put, the shadow stack is a separate stack from the call stack that is synchronized with the call stack so that whenever a frame is added to the call stack, the return address of that frame is added to the shadow stack. Whenever a frame is popped from the top of the call stack, the return address at the top of the shadow stack is popped from the shadow stack accordingly. If the popped return address does not match the return address in the popped frame, an error has occurred and remedial action can be taken.

[0029] Figure 2 An example of source code 110 compiled by a compiler 112 to generate an executable program 114 is shown. Source code 110 includes various functions and function calls. Compiler 112 translates the source code into an executable program 114, which can be in the form of machine code, byte code, intermediate code, object code, etc. The compiled executable program 114 has code / instruction units corresponding to the functions in the source code. Except perhaps in some managed runtime environments, the compiler also adds instructions for implementing a call stack to the executable program 114. As discussed in detail below, in an embodiment using a software-based shadow stack, compiler 112 also adds instrumentation code for implementing the shadow stack.

[0030] Figure 3 Details of the call stack 102 and shadow stack 104 are shown. The call stack 102 consists of frames 120, each for a still pending function call. Each frame 120 includes a return address 122, as well as memory for local variables 124 and parameters 126, as appropriate. Figure 3Examples include functions main(), bar(), and foo(). The main() function is coded as calling foo(), and foo() is coded as calling bar(). Figure 3 The call stack 102 shown in FIG reflects the executable program 114 at the time when foo() has been called and is still executing. Figure 3 As shown, assuming the call stack 102 is not corrupted, the shadow stack 104 should contain a copy 126 of the return addresses in each frame in the call stack, in the same order.

[0031] Figure 4 1 shows how to maintain the call stack 102 and the shadow stack 104. As discussed in detail below, Figure 4 The shadow stack management steps in the embodiment of the present invention can be performed by the processor's special shadow stack hardware, by software, or both. When the executing program 100 calls a function at step 130, a new frame 134 is pushed onto the call stack 102 at step 132. The new frame 134 includes a return address corresponding to the point at which the called function was called. At step 136, based on the same function call, a new return address 138 (the same return address in the new frame 134) is pushed onto the shadow stack 104. The steps of adding to the stack can be performed in any order or in parallel.

[0032] In step 140, executive program 100 is executing the called function, and this function returns (for example exits).In step 142, from call stack, pop-up returns to the frame of self-function, and in step 144, from shadow stack, pop-up the top return address on shadow stack.As most steps described herein, the step for removing from stack can be performed in any order or executed in parallel.In addition, removal / exit process comprises some logic (no matter whether it is hardware or software) to compare the return address in the pop-up frame with the return address popped from shadow stack, and if the two do not match, then respond accordingly.But, for back tracing, do not necessarily need to compare, if can realize shadow stack under the situation that there is no any comparison / remediation step, then can further reduce little back tracing overhead.

[0033] As mentioned above, the shadow stack can be implemented in hardware or software. Figure 5 A software-based shadow stack implementation is shown. In this embodiment, the compiler inserts instrumentation code that implements the shadow stack into its converted output. Typically, instrumentation code 150 is placed near each function call 152. Instrumentation code 150 may include entry logic 154 and exit logic 156. Entry logic 154 may push the relevant return address onto the shadow stack, etc. Exit logic 156 may pop the top of the shadow stack and check the popped return address against the return address in the corresponding call frame.

[0034] Figure 6A hardware-based shadow stack implementation is shown. Processor 160 has circuitry that implements various instructions in the processor instruction set. In one embodiment, the processor's implementation of the call instruction includes normal call logic 164 and shadow stack logic 166. Normal call logic 164 is the call instruction control flow logic that exists in a typical processor, regardless of whether the processor implements a shadow stack. Shadow stack logic 166 performs the shadow stack function described above, but is associated with call instruction 162. Some processors may have registers for controlling whether the shadow stack logic is active, which may control the implementation and / or backtrace use of shadow stack logic 166, etc. The executable program may not see the shadow stack, which is implemented without instrumentation code. In other words, the same executable file can run on (i) a processor that lacks shadow stack support (and the execution will not have a shadow stack) and (ii) another processor that has shadow stack support (and will have a shadow stack) without modification.

[0035] In hardware and software implementations, the shadow stack is assumed to be readable at any time while a thread or program is executing, whether by the program / thread whose calls the shadow stack is tracing, or by another component such as a debugger or runtime environment.

[0036] Figure 7 The figure shows how to use the shadow stack to satisfy the backtrace request 170. The compiled program 100 is being executed. As described above, the program calls functions within functions, thereby forming a function call chain, and the corresponding state is reflected in the call stack and the shadow stack. The backtrace request 170 can be received during any execution point. The backtrace request 170 can be an application programming interface (API) call, a call to a backtrace function included in the executable program 100, etc. The backtrace request can also be issued by an exception handler, a signal handler called by an external signal, etc.

[0037] Based on the backtrace request 170, the shadow stack 104 is accessed and read by code in the program 100 (or code linked to the program 100), by shadow stack instructions implemented by the processor, or by a combination thereof. A complete or partial copy 172 of the shadow stack 104 is captured (as used herein, a "copy" of a shadow stack refers to a complete copy or a selective / partial copy). In some embodiments, the return addresses copied from the shadow stack can be limited to the first N subsets of available addresses. Such limitations may come from hardware constraints (e.g., buffer size), variables set in the program, parameters passed to the backtrace request, etc.

[0038] Finally, the shadow stack copy 172 is merged into the trace or debug output 174. Any of a number of known means for capturing diagnostic information can be supplemented with shadow stack backtrace data in this manner. In one embodiment, any known method for requesting and storing backtrace data can be used by modifying this method so that return address data is obtained from the shadow stack in addition to or instead of the call stack. For example, the return address (which is just a number) can be converted from symbolic information into a function name, line number, file number, etc. This complete stack trace can then be stored in a log file, output to a screen, or sent over a network as telemetry for crash analysis, etc.

[0039] Figure 8 The process of using a shadow stack is shown. At step 200, during program execution, a stack trace or backtrace is requested by the program's internal logic or a component communicating with the program. At step 202, information about the shadow stack can optionally be obtained, such as whether the shadow stack exists, its location, current size (or number of elements), the element format of the shadow stack, security information, properties of the shadow stack (e.g., whether it is implemented in hardware or software), etc.

[0040] At step 204, if shadow stack information is available, the shadow stack information can be used to determine how or whether to execute the backtrace request. For example, a backtrace request may not generate a backtrace unless a shadow stack is available (or has certain characteristics). Properties of the shadow stack (e.g., size, location, size / number of elements, permissions, etc.) can also be used to access and copy the shadow stack.

[0041] In step 206, a backtrace is generated using the shadow stack. As described above, in some embodiments, the backtrace is a verbatim copy of the shadow stack or a portion thereof. In other embodiments, the return address in the shadow stack is used to identify the associated corresponding function, the source code module and the line number defining the return address, the name of the called function, the line number in the calling function, information about the associated function (e.g., return type, parameter types / names), etc.

[0042] Figure 9Shadow stack content 220 is shown used in conjunction with other information to generate a backtrace 222. In some embodiments, the return address in shadow stack content 222 can be used in conjunction with call stack 102 and / or program / module metadata 224 to derive a rich backtrace 222. Program / module metadata 224 is metadata present in object files, symbol tables, source code files, and the like. Backtrace generation function 226 receives shadow stack content 220. Backtrace generation function 226 also receives or accesses program / module metadata 226 and / or call stack 102. This information can be synthesized / combined in various ways. By correlating the return address in the shadow stack content with the frames and return addresses in the call stack, the values ​​of parameters and local variables can be retrieved, the names of functions and modules can be found, the line number of the call can be obtained, and so on. Conceptually, the return address in shadow stack content 220 can be used as an index into additional data; the shadow stack allows for near-zero-cost reconstruction of call chains and can enrich call chains with additional diagnostic information from other sources. In whatever form, the backtrace 222 may be output through existing diagnostic / debugging / telemetry solutions, which may involve using an API to output diagnostic data, collecting the formatted output in a log file, sending the log file to a collection service, etc.

[0043] Another example is data corruption on the regular stack. This is common because local variables are also stored on the regular stack, so a bug in the code could cause the return address on the regular stack to be overwritten. Because the shadow stack has no local variables, the program shouldn't need to touch any memory on the shadow stack, making it much less likely to be corrupted. In the hardware case, the hardware can force the shadow stack to be read-only, while in the software case, the operating system can also make it read-only for everyone except itself (for pushing and popping return addresses). In either case, if the return address on the regular stack is corrupted, an extra copy of the return address on the shadow stack can be swapped in to correct the problem. Then, if there's no other corruption, the program may continue to run. If there's other corruption, at least we can still obtain a successful stack trace to catch the culprit causing the corruption.

[0044] Furthermore, when unwinding the stack, if there is corruption in the middle of the stack, unwinding will fail at the corrupted location, and further unwinding will be impossible because the data on the stack is wrong, so the location of the next return address is unknown. However, if the shadow stack is available, even if the shadow stack itself has some corrupted entries, the corrupted return address entries can be skipped and unwinding can continue because it is known that the return addresses are continuous in memory.

[0045] Figure 10 shows the various contexts in which backtracking logic can be implemented. Figure 10In one embodiment shown at the top, the program 100 includes a call to an API for capturing a backtrace. The API can be any known API for debugging or capturing a backtrace. However, the logic that implements the API uses a shadow stack. The API can also have additional functions / methods related to using a shadow stack. For example, the API can define functions for setting up prerequisites for satisfying a backtrace request (e.g., a shadow stack is available, a shadow stack is available and supported by the hardware, etc.). The API can also facilitate backward compatibility. The backtrace function can also be completely contained in the program, such as Figure 10 In another embodiment, an environment 230 such as a debugger, a managed code environment, an interpreter, etc., both executes the program and provides a backtrace function.

[0046] Figure 11 An example backtrace output 240 is shown. The example includes a string 242 generated based on the shadow stack data. Any known style of backtrace format and content can be used. Settings, different backtrace functions (e.g., backtrace_raw() or backtrace_symbols()), or backtrace function parameters can be used to control the style and content of the backtrace, ranging from a list of raw memory addresses to detailed information and graphics of the functions that appear in the backtrace.

[0047] Although the above examples involve compilers, most of the techniques can be easily applied to interpreters. In this case, the interpreter can be configured to use the shadow stack in a similar manner. From the program's perspective, the interpreter should be identical; both compilers and interpreters have call / ret instructions that are executed by the processor.

[0048] Some call stack implementations use multiple call stacks that are linked together. In this case, the corresponding shadow stacks are linked, and unwinding the current call chain of a backtrace may involve unwinding the linked shadow stacks.

[0049] The term "program" used in this article is also considered to refer to threads. Typically, each thread has its own call stack and shadow stack.

[0050] Figure 12 The details of a computing device 300 on which the above-described embodiments can be implemented are shown. The technical disclosure herein will be sufficient for a programmer to write software, and / or configure reconfigurable processing hardware (e.g., field programmable gate array (FPGA)), and / or design an application specific integrated circuit (ASIC) or the like to run on the computing device or host 300 (possibly through a cloud API) to implement the embodiments described herein.

[0051] The computing device or host 300 may have one or more displays 322, a network interface 324 (or several), storage hardware 326, and processing hardware 328, which may be any combination of one or more of the following: a central processing unit, a graphics processing unit, an analog-to-digital converter, a bus chip, an FPGA, an ASIC, an application-specific standard product (ASSP), or a complex programmable logic device (CPLD). The storage hardware 326 may be any combination of magnetic memory, static memory, volatile memory, non-volatile memory, optically or magnetically readable material, or the like. As used herein, the term "storage" does not refer to signals or energy per se, but rather to the physical devices and states of matter used to read and / or store information. The hardware elements of the computing device or host 300 may cooperate in a manner well known in the art of machine computing. In addition, input devices may be integrated with or communicate with the computing device or host 300. The computing device or host 300 may have any form factor or be used in any type of containing device. The computing device or host 300 may be in the form of a handheld device, such as a smartphone, a tablet computer, a gaming device, a server, a rack-mounted or backplane-mounted computer, a system-on-chip, or other.

[0052] The above-described embodiments and features may be implemented in the form of information stored in a volatile or non-volatile computer or device readable medium. This is considered to include at least media such as optical storage (e.g., compact disk read-only memory (CD-ROM)), magnetic media, flash read-only memory (ROM), or any current or future means of storing digital information. The stored information may be in the form of machine-executable instructions (e.g., compiled executable binary code), source code, bytecode, or any other information that can be used to enable or configure a computing device to perform the various embodiments described above. This is considered to include at least volatile memory such as random access memory (RAM) and / or virtual memory that stores information such as central processing unit instructions during execution of the program of the embodiments, and non-volatile media that stores information that allows loading and execution of programs or executable files. The embodiments and features may be executed on any type of computing device, including portable devices, workstations, servers, mobile wireless devices, and the like.

Claims

1. A method comprising: executing, by a processor, a program comprising functions, each function comprising corresponding code for the corresponding function and a call to invoke the function, the executing comprising maintaining a call stack, the call stack comprising frames corresponding to respective invocations of the functions by the calls, each frame comprising a corresponding return address; Maintaining a shadow stack, wherein maintaining the shadow stack includes adding a return address to the shadow stack / removing the return address from the shadow stack corresponding to adding a frame to the call stack / removing the frame from the call stack; as well as Receive a request for a stack trace and access both the call stack and the shadow stack based on the request to generate the stack trace in the future by combining information obtained from the shadow stack with information obtained from the call stack, the information obtained from the shadow stack including a corresponding return address, and the corresponding return address obtained from the shadow stack serving as an index for obtaining the information from the call stack.

2. The method according to claim 1 further includes obtaining at least some corresponding function metadata from the call stack for the first return address in the shadow stack.

3. The method according to claim 2 further includes obtaining additional corresponding function metadata from the program for the first return address in the shadow stack. 4 . The method according to claim 1 , wherein the processor implements the shadow stack by providing a call instruction, and a single execution of the call instruction causes a corresponding return address to be pushed onto the call stack and the shadow stack. The method of claim 1 , wherein the maintaining of the shadow stack is performed by the program. 6 . The method of claim 1 , wherein generating the stack trace comprises copying the shadow stack and storing the copy of the shadow stack and storing an indication that the copy of the shadow stack is associated with the program.

7. The method of claim 1 , wherein the performing further comprises: An enriched backtrace is exported, the backtrace including the corresponding return address from the shadow stack and additional corresponding information from the call stack.

8. The method of claim 1 , wherein using the corresponding return address from the shadow stack as the index to the information retrieved from the call stack comprises: The corresponding return address in the shadow stack is associated with a frame and return address in the call stack.

9. Computer-readable storage hardware storing instructions configured to cause a computing device to perform a process, the computing device comprising processing hardware and memory, the process comprising: The processing hardware executes a program, the execution including providing a call stack and a shadow stack in the memory, the call stack including stack frames, each stack frame including a corresponding return address, some of the stack frames also including corresponding local variables and / or parameters, the shadow stack including a return address corresponding to the return address in the call stack, and providing the call stack and the shadow stack including: When a function is called by the program, adding a corresponding stack frame to the call stack and adding a corresponding return address to the shadow stack; and When the function is exited by the program, removing the corresponding stack frame from the call stack and removing the corresponding return address from the shadow stack; and A backtrace request associated with the program is received, and based on the backtrace request, a backtrace of the program is formed by combining information obtained from both the call stack and the shadow stack, the information obtained from the shadow stack including a corresponding return address, the corresponding return address from the shadow stack being used as an index to obtain the information from the call stack.

10. The computer-readable storage hardware of claim 9, the process further comprising determining that the shadow stack is available, wherein forming the backtrace is performed only if the shadow stack has been determined to be available.

11. The computer-readable storage hardware of claim 9, wherein forming the backtrace of the program further comprises: using the corresponding return address in the shadow stack to identify a text string corresponding to the corresponding return address in the shadow stack, and The text strings are included in the backtrace, the backtrace including the text strings arranged in an order corresponding to an order of the corresponding return addresses in the shadow stack when the backtrace request is received.

12. The computer-readable storage hardware of claim 9, wherein the process further comprises configuring execution of the program based on a second request from the program such that the backtrace request captures a corresponding backtrace only when a shadow stack is available.

13. The computer-readable storage hardware of claim 9, wherein providing the call stack and the shadow stack comprises: The processing hardware provides a call instruction, a single execution of which causes a first return address to be pushed onto both the call stack and the shadow stack.

14. The computer-readable storage hardware of claim 9, wherein the program comprises a plurality of call stacks and corresponding shadow stacks.

15. The computer-readable storage hardware of claim 9, wherein forming the backtrace of the program further comprises: For a first return address in the shadow stack, at least some corresponding function metadata is obtained from the call stack.

16. The computer-readable storage hardware of claim 9, wherein using the corresponding return address from the shadow stack as the index to the information retrieved from the call stack comprises: The corresponding return address in the shadow stack is associated with a frame and return address in the call stack.

17. A device comprising: Processing hardware; as well as Storage hardware storing instructions, wherein the instructions are configured to cause the processing hardware to perform a process, the process comprising: Executing a program, said executing including maintaining a call stack and a corresponding shadow stack; as well as When the program is executing and a function chain has been called by the program, a request to generate a backtrace for the program is responded to by copying a return address from the shadow stack and obtaining additional information from the call stack, and outputting a combination of the copied return address and the additional information obtained from the call stack, the return address from the shadow stack being used as an index for obtaining the additional information from the call stack.

18. The apparatus of claim 17, wherein the processing hardware comprises hardware instructions including a call instruction configured to manage the shadow stack.

19. The apparatus of claim 18, wherein the hardware instructions further comprise a return instruction, the call instruction being configured to push an address onto both the call stack and the shadow stack, and the return instruction being configured to compare an address from the call stack with a corresponding address from the shadow stack.

20. The apparatus of claim 17, the process further comprising the program calling a backtrace function to request the backtrace, The backtrace function determines whether the shadow stack is available or accessible, and generates the backtrace based on determining that the shadow stack is available or accessible.

21. The apparatus of claim 17, wherein the maintaining of the shadow stack is performed by the program.

22. The apparatus of claim 17 , wherein the process further comprises the program calling a backtrace function to request the backtrace, wherein the backtrace function uses the return address in the shadow stack to identify text strings corresponding to the return addresses from the shadow stack from the program or the call stack, respectively, and includes the text strings in the backtrace.

23. The apparatus of claim 17, wherein using the return address from the shadow stack as the index to the information retrieved from the call stack comprises: The return address in the shadow stack is associated with a frame and a return address in the call stack.

Citation Information

Patent Citations

  • A mean for detecting a tamper of a return address in that stack

    CN109409083A

  • Debugging platform-independent software applications and related code components

    US20030204838A1