1 1.1 christos \input texinfo @c -*- Texinfo -*- 2 1.1 christos @setfilename sframe-spec.info 3 1.1 christos @settitle The SFrame Format 4 1.1 christos 5 1.1 christos @copying 6 1.1.1.2 christos Copyright @copyright{} 2021-2024 Free Software Foundation, Inc. 7 1.1 christos 8 1.1 christos Permission is granted to copy, distribute and/or modify this document 9 1.1 christos under the terms of the GNU General Public License, Version 3 or any 10 1.1 christos later version published by the Free Software Foundation. A copy of the 11 1.1 christos license is included in the section entitled ``GNU General Public 12 1.1 christos License''. 13 1.1 christos 14 1.1 christos @end copying 15 1.1 christos 16 1.1 christos @dircategory Software development 17 1.1 christos @direntry 18 1.1 christos * SFrame: (sframe-spec). The Simple Frame format. 19 1.1 christos @end direntry 20 1.1 christos 21 1.1 christos @titlepage 22 1.1 christos @title The SFrame Format 23 1.1.1.2 christos @subtitle Version 2 24 1.1 christos @author Indu Bhagat 25 1.1 christos 26 1.1 christos @page 27 1.1 christos @vskip 0pt plus 1filll 28 1.1 christos @insertcopying 29 1.1 christos @end titlepage 30 1.1 christos @contents 31 1.1 christos 32 1.1 christos @ifnottex 33 1.1 christos @node Top 34 1.1 christos @top The SFrame format 35 1.1 christos 36 1.1.1.2 christos This manual describes version 2 of the SFrame file format. SFrame stands for 37 1.1.1.3 christos Simple Frame. The SFrame format keeps track of the minimal necessary 38 1.1.1.2 christos information needed for generating stack traces: 39 1.1 christos 40 1.1 christos @itemize @minus 41 1.1 christos @item 42 1.1 christos Canonical Frame Address (CFA). 43 1.1 christos @item 44 1.1 christos Frame Pointer (FP). 45 1.1 christos @item 46 1.1 christos Return Address (RA). 47 1.1 christos @end itemize 48 1.1 christos 49 1.1.1.2 christos The reason for existence of the SFrame format is to provide a simple, fast and 50 1.1.1.2 christos low-overhead mechanism to generate stack traces. 51 1.1 christos 52 1.1 christos @menu 53 1.1.1.2 christos * Introduction:: 54 1.1.1.3 christos * SFrame Section:: 55 1.1.1.3 christos * ABI/arch-specific Definition:: 56 1.1.1.3 christos 57 1.1.1.3 christos Appendices 58 1.1.1.3 christos * Generating Stack Traces using SFrame:: 59 1.1.1.3 christos 60 1.1 christos * Index:: 61 1.1 christos @end menu 62 1.1 christos 63 1.1 christos @end ifnottex 64 1.1 christos 65 1.1.1.2 christos @node Introduction 66 1.1.1.2 christos @chapter Introduction 67 1.1.1.2 christos @cindex Introduction 68 1.1.1.2 christos 69 1.1.1.2 christos @menu 70 1.1.1.2 christos * Overview:: 71 1.1.1.2 christos * Changes from Version 1 to Version 2:: 72 1.1.1.2 christos @end menu 73 1.1.1.2 christos 74 1.1 christos @node Overview 75 1.1.1.2 christos @section Overview 76 1.1 christos @cindex Overview 77 1.1 christos 78 1.1.1.2 christos The SFrame stack trace information is provided in a loaded section, known as the 79 1.1 christos @code{.sframe} section. When available, the @code{.sframe} section appears in 80 1.1 christos a new segment of its own, PT_GNU_SFRAME. 81 1.1 christos 82 1.1 christos The SFrame format is currently supported only for select ABIs, namely, AMD64 83 1.1 christos and AAPCS64. 84 1.1 christos 85 1.1.1.2 christos A portion of the SFrame format follows an unaligned on-disk representation. 86 1.1.1.2 christos Some data structures, however, (namely the SFrame header and the SFrame 87 1.1.1.2 christos function descriptor entry) have elements at their natural boundaries. All data 88 1.1.1.2 christos structures are packed, unless otherwise stated. 89 1.1.1.2 christos 90 1.1 christos The contents of the SFrame section are stored in the target endianness, i.e., 91 1.1.1.3 christos in the endianness of the system on which the section is targeted to be used. 92 1.1 christos An SFrame section reader may use the magic number in the SFrame header to 93 1.1 christos identify the endianness of the SFrame section. 94 1.1 christos 95 1.1 christos Addresses in this specification are expressed in bytes. 96 1.1 christos 97 1.1.1.2 christos The rest of this specification describes the current version of the format, 98 1.1.1.2 christos @code{SFRAME_VERSION_2}, in detail. Additional sections outline the major 99 1.1.1.2 christos changes made to each previously published version of the SFrame stack trace 100 1.1.1.2 christos format. 101 1.1.1.2 christos 102 1.1 christos The associated API to decode, probe and encode the SFrame section, provided via 103 1.1 christos @code{libsframe}, is not accompanied here at this time. This will be added 104 1.1 christos later. 105 1.1 christos 106 1.1 christos This document is intended to be in sync with the C code in @file{sframe.h}. 107 1.1.1.2 christos Please report discrepancies between the two, if any. 108 1.1.1.2 christos 109 1.1.1.2 christos @node Changes from Version 1 to Version 2 110 1.1.1.2 christos @section Changes from Version 1 to Version 2 111 1.1.1.2 christos @cindex Changes from Version 1 to Version 2 112 1.1.1.2 christos 113 1.1.1.2 christos The following is a list of the changes made to the SFrame stack trace format 114 1.1.1.2 christos since Version 1 was published. 115 1.1.1.2 christos 116 1.1.1.2 christos @itemize @bullet 117 1.1.1.2 christos @item 118 1.1.1.3 christos Add an unsigned 8-bit integral field to the SFrame function descriptor entry to 119 1.1.1.3 christos encode the size of the repetitive code blocks. Such code blocks, e.g, pltN 120 1.1.1.3 christos entries, use an SFrame function descriptor entry of type 121 1.1.1.3 christos SFRAME_FDE_TYPE_PCMASK. 122 1.1.1.3 christos @item 123 1.1.1.3 christos Add an unsigned 16-bit integral field to the SFrame function descriptor entry 124 1.1.1.3 christos to serve as padding. This helps ensure natural alignment for the members of 125 1.1.1.3 christos the data structure. 126 1.1.1.2 christos @item 127 1.1.1.3 christos The above two imply that each SFrame function descriptor entry has a fixed size 128 1.1.1.2 christos of 20 bytes instead of its size of 17 bytes in SFrame format version 1. 129 1.1.1.2 christos @end itemize 130 1.1 christos 131 1.1.1.3 christos SFrame version 1 is now obsolete and should not be used. 132 1.1.1.3 christos 133 1.1.1.3 christos @node SFrame Section 134 1.1.1.3 christos @chapter SFrame Section 135 1.1.1.3 christos @cindex SFrame Section 136 1.1 christos 137 1.1 christos The SFrame section consists of an SFrame header, starting with a preamble, and 138 1.1.1.3 christos two other sub-sections, namely the SFrame function descriptor entry (SFrame 139 1.1.1.3 christos FDE) sub-section, and the SFrame frame row entry (SFrame FRE) sub-section. 140 1.1 christos 141 1.1 christos @menu 142 1.1 christos * SFrame Preamble:: 143 1.1 christos * SFrame Header:: 144 1.1 christos * SFrame Function Descriptor Entries:: 145 1.1 christos * SFrame Frame Row Entries:: 146 1.1 christos @end menu 147 1.1 christos 148 1.1 christos @node SFrame Preamble 149 1.1 christos @section SFrame Preamble 150 1.1 christos @cindex SFrame preamble 151 1.1 christos 152 1.1.1.3 christos The preamble is a 32-bit packed structure; the only part of the SFrame section 153 1.1.1.3 christos whose format cannot vary between versions. 154 1.1 christos 155 1.1 christos @example 156 1.1 christos typedef struct sframe_preamble 157 1.1 christos @{ 158 1.1 christos uint16_t sfp_magic; 159 1.1 christos uint8_t sfp_version; 160 1.1 christos uint8_t sfp_flags; 161 1.1 christos @} ATTRIBUTE_PACKED sframe_preamble; 162 1.1 christos @end example 163 1.1 christos 164 1.1.1.2 christos Every element of the SFrame preamble is naturally aligned. 165 1.1.1.2 christos 166 1.1 christos All values are stored in the endianness of the target system for which the 167 1.1 christos SFrame section is intended. Further details: 168 1.1 christos 169 1.1.1.3 christos @multitable {Offset} {@code{uint16_t}} {@code{sfp_version}} {The magic number for SFrame section: 0xdee2.} 170 1.1.1.3 christos @headitem Offset @tab Type @tab Name @tab Description 171 1.1 christos @item 0x00 172 1.1.1.3 christos @tab @code{uint16_t} 173 1.1.1.3 christos @tab @code{sfp_magic} 174 1.1 christos @tab The magic number for SFrame section: 0xdee2. Defined as a macro @code{SFRAME_MAGIC}. 175 1.1 christos @tindex SFRAME_MAGIC 176 1.1 christos 177 1.1 christos @item 0x02 178 1.1.1.3 christos @tab @code{uint8_t} 179 1.1.1.3 christos @tab @code{sfp_version} 180 1.1.1.3 christos @tab The version number of this SFrame section. @xref{SFrame Version}, for the 181 1.1 christos set of valid values. Current version is 182 1.1.1.3 christos @code{SFRAME_VERSION_2}. 183 1.1 christos 184 1.1 christos @item 0x03 185 1.1.1.3 christos @tab @code{uint8_t} 186 1.1.1.3 christos @tab @code{sfp_flags} 187 1.1.1.3 christos @tab Flags (section-wide) for this SFrame section. @xref{SFrame Flags}, for the 188 1.1 christos set of valid values. 189 1.1 christos @end multitable 190 1.1 christos 191 1.1 christos @menu 192 1.1.1.3 christos * SFrame Magic Number and Endianness:: 193 1.1.1.3 christos * SFrame Version:: 194 1.1.1.3 christos * SFrame Flags:: 195 1.1 christos @end menu 196 1.1 christos 197 1.1.1.3 christos @node SFrame Magic Number and Endianness 198 1.1.1.3 christos @subsection SFrame Magic Number and Endianness 199 1.1 christos 200 1.1 christos @cindex endianness 201 1.1.1.3 christos @cindex SFrame magic number 202 1.1 christos SFrame sections are stored in the target endianness of the system that consumes 203 1.1.1.3 christos them. A consumer library reading or writing SFrame sections should detect 204 1.1.1.3 christos foreign-endianness by inspecting the SFrame magic number in the 205 1.1.1.3 christos @code{sfp_magic} field in the SFrame header. It may then provide means to 206 1.1.1.3 christos endian-flip the SFrame section as necessary. 207 1.1 christos 208 1.1.1.3 christos @node SFrame Version 209 1.1.1.3 christos @subsection SFrame Version 210 1.1 christos 211 1.1 christos The version of the SFrame format can be determined by inspecting 212 1.1 christos @code{sfp_version}. The following versions are currently valid: 213 1.1 christos 214 1.1 christos @tindex SFRAME_VERSION_1 215 1.1 christos @cindex SFrame versions 216 1.1.1.2 christos @multitable {SFRAME_VERSION_2} {Number} {Current version, under development.} 217 1.1.1.3 christos @headitem Version Name @tab Number @tab Description 218 1.1 christos @item @code{SFRAME_VERSION_1} 219 1.1.1.2 christos @tab 1 @tab First version, obsolete. 220 1.1.1.2 christos @item @code{SFRAME_VERSION_2} 221 1.1.1.2 christos @tab 2 @tab Current version, under development. 222 1.1 christos @end multitable 223 1.1 christos 224 1.1.1.2 christos This document describes @code{SFRAME_VERSION_2}. 225 1.1 christos 226 1.1.1.3 christos @node SFrame Flags 227 1.1.1.3 christos @subsection SFrame Flags 228 1.1.1.3 christos @cindex SFrame Flags 229 1.1 christos 230 1.1 christos The preamble contains bitflags in its @code{sfp_flags} field that 231 1.1 christos describe various section-wide properties. 232 1.1 christos 233 1.1 christos The following flags are currently defined. 234 1.1 christos 235 1.1 christos @multitable {@code{SFRAME_F_FRAME_POINTER}} {Versions} {Value} {Function Descriptor Entries} 236 1.1 christos @headitem Flag @tab Versions @tab Value @tab Meaning 237 1.1 christos @tindex SFRAME_F_FDE_SORTED 238 1.1 christos @item @code{SFRAME_F_FDE_SORTED} @tab All @tab 0x1 @tab Function Descriptor 239 1.1 christos Entries are sorted on PC. 240 1.1 christos @tindex SFRAME_F_FRAME_POINTER 241 1.1 christos @item @code{SFRAME_F_FRAME_POINTER} @tab All @tab 0x2 242 1.1.1.3 christos @tab All functions in the object file preserve frame pointer. 243 1.1 christos @end multitable 244 1.1 christos 245 1.1.1.3 christos The purpose of SFRAME_F_FRAME_POINTER flag is to facilitate stack tracers to 246 1.1.1.3 christos reliably fallback on the frame pointer based stack tracing method, if SFrame 247 1.1.1.3 christos information is not present for some function in the SFrame section. 248 1.1.1.3 christos 249 1.1 christos Further flags may be added in future. 250 1.1 christos 251 1.1 christos @node SFrame Header 252 1.1 christos @section SFrame Header 253 1.1 christos @cindex SFrame header 254 1.1 christos 255 1.1 christos The SFrame header is the first part of an SFrame section. It begins with the 256 1.1 christos SFrame preamble. All parts of it other than the preamble 257 1.1 christos (@pxref{SFrame Preamble}) can vary between SFrame file versions. It contains 258 1.1 christos things that apply to the section as a whole, and offsets to the various other 259 1.1 christos sub-sections defined in the format. As with the rest of the SFrame section, 260 1.1 christos all values are stored in the endianness of the target system. 261 1.1 christos 262 1.1 christos The two sub-sections tile the SFrame section: each section runs from the offset 263 1.1 christos given until the start of the next section. An explicit length is given for the 264 1.1 christos last sub-section, the SFrame Frame Row Entry (SFrame FRE) sub-section. 265 1.1 christos 266 1.1 christos @example 267 1.1 christos typedef struct sframe_header 268 1.1 christos @{ 269 1.1 christos sframe_preamble sfh_preamble; 270 1.1 christos uint8_t sfh_abi_arch; 271 1.1 christos int8_t sfh_cfa_fixed_fp_offset; 272 1.1 christos int8_t sfh_cfa_fixed_ra_offset; 273 1.1 christos uint8_t sfh_auxhdr_len; 274 1.1 christos uint32_t sfh_num_fdes; 275 1.1 christos uint32_t sfh_num_fres; 276 1.1 christos uint32_t sfh_fre_len; 277 1.1 christos uint32_t sfh_fdeoff; 278 1.1 christos uint32_t sfh_freoff; 279 1.1 christos @} ATTRIBUTE_PACKED sframe_header; 280 1.1 christos @end example 281 1.1 christos 282 1.1.1.2 christos Every element of the SFrame header is naturally aligned. 283 1.1.1.2 christos 284 1.1 christos The sub-section offsets, namely @code{sfh_fdeoff} and @code{sfh_freoff}, in the 285 1.1 christos SFrame header are relative to the @emph{end} of the SFrame header; they are 286 1.1 christos each an offset in bytes into the SFrame section where the SFrame FDE 287 1.1 christos sub-section and the SFrame FRE sub-section respectively start. 288 1.1 christos 289 1.1.1.3 christos The SFrame section contains @code{sfh_num_fdes} number of fixed-length array 290 1.1.1.3 christos elements in the SFrame FDE sub-section. Each array element is of type SFrame 291 1.1.1.3 christos function descriptor entry; each providing a high-level function description for 292 1.1.1.3 christos the purpose of stack tracing. More details in a subsequent section. 293 1.1.1.3 christos @xref{SFrame Function Descriptor Entries}. 294 1.1.1.3 christos 295 1.1.1.3 christos Next, the SFrame FRE sub-section, starting at offset @code{sfh_fre_off}, 296 1.1.1.3 christos describes the stack trace information for each function, using a total of 297 1.1.1.3 christos @code{sfh_num_fres} number of variable-length array elements. Each array 298 1.1.1.3 christos element is of type SFrame frame row entry. 299 1.1.1.3 christos @xref{SFrame Frame Row Entries}. 300 1.1.1.3 christos 301 1.1 christos SFrame header allows specifying explicitly the fixed offsets from CFA, if any, 302 1.1 christos from which FP or RA may be recovered. For example, in AMD64, the stack offset 303 1.1.1.3 christos of the return address is @code{CFA - 8}. Since these offsets are expected to 304 1.1.1.3 christos be in close vicinity to the CFA in most ABIs, @code{sfh_cfa_fixed_fp_offset} 305 1.1.1.3 christos and @code{sfh_cfa_fixed_ra_offset} are limited to signed 8-bit integers. 306 1.1.1.3 christos 307 1.1.1.3 christos @cindex Provisions for future ABIs 308 1.1.1.3 christos The SFrame format has made some provisions for supporting more 309 1.1.1.3 christos ABIs/architectures in the future. One of them is the concept of the auxiliary 310 1.1.1.3 christos SFrame header. Bytes in the auxiliary SFrame header may be used to convey 311 1.1.1.3 christos further ABI-specific information. The @code{sframe_header} structure provides 312 1.1.1.3 christos an unsigned 8-bit integral field to denote the size (in bytes) of an auxiliary 313 1.1.1.3 christos SFrame header. The auxiliary SFrame header follows right after the 314 1.1.1.3 christos @code{sframe_header} structure. As for the calculation of the sub-section 315 1.1.1.3 christos offsets, namely @code{sfh_fdeoff} and @code{sfh_freoff}, the @emph{end} of 316 1.1.1.3 christos SFrame header must be the end of the auxiliary SFrame header, if the latter is 317 1.1.1.3 christos present. 318 1.1 christos 319 1.1.1.2 christos Putting it all together: 320 1.1 christos 321 1.1.1.3 christos @multitable {Offset} {@code{uint32_t}} {@code{sfh_cfa_fixed_fp_offset}} {The number of SFrame FREs in the} 322 1.1.1.3 christos @headitem Offset @tab Type @tab Name @tab Description 323 1.1 christos @item 0x00 324 1.1.1.3 christos @tab @code{sframe_ @* preamble} 325 1.1.1.3 christos @tab @code{sfh_preamble} 326 1.1 christos @tab The SFrame preamble. @xref{SFrame Preamble}. 327 1.1 christos 328 1.1 christos @item 0x04 329 1.1.1.3 christos @tab @code{uint8_t} 330 1.1.1.3 christos @tab @code{sfh_abi_arch} 331 1.1.1.3 christos @tab The ABI/arch identifier. @xref{SFrame ABI/arch Identifier}. 332 1.1 christos 333 1.1 christos @item 0x05 334 1.1.1.3 christos @tab @code{int8_t} 335 1.1.1.3 christos @tab @code{sfh_cfa_fixed_fp_offset} 336 1.1 christos @tab The CFA fixed FP offset, if any. 337 1.1 christos 338 1.1 christos @item 0x06 339 1.1.1.3 christos @tab @code{int8_t} 340 1.1.1.3 christos @tab @code{sfh_cfa_fixed_ra_offset} 341 1.1 christos @tab The CFA fixed RA offset, if any. 342 1.1 christos 343 1.1 christos @item 0x07 344 1.1.1.3 christos @tab @code{uint8_t} 345 1.1.1.3 christos @tab @code{sfh_auxhdr_len} 346 1.1.1.2 christos @tab Size in bytes of the auxiliary header that follows the 347 1.1 christos @code{sframe_header} structure. 348 1.1 christos 349 1.1 christos @item 0x08 350 1.1.1.3 christos @tab @code{uint32_t} 351 1.1.1.3 christos @tab @code{sfh_num_fdes} 352 1.1 christos @tab The number of SFrame FDEs in the section. 353 1.1 christos 354 1.1.1.3 christos @item 0x0c 355 1.1.1.3 christos @tab @code{uint32_t} 356 1.1.1.3 christos @tab @code{sfh_num_fres} 357 1.1 christos @tab The number of SFrame FREs in the section. 358 1.1 christos 359 1.1 christos @item 0x10 360 1.1.1.3 christos @tab @code{uint32_t} 361 1.1.1.3 christos @tab @code{sfh_fre_len} 362 1.1 christos @tab The length in bytes of the SFrame FRE sub-section. 363 1.1 christos 364 1.1 christos @item 0x14 365 1.1.1.3 christos @tab @code{uint32_t} 366 1.1.1.3 christos @tab @code{sfh_fdeoff} 367 1.1.1.3 christos @tab The offset in bytes to the SFrame FDE sub-section. 368 1.1 christos 369 1.1 christos @item 0x18 370 1.1.1.3 christos @tab @code{uint32_t} 371 1.1.1.3 christos @tab @code{sfh_freoff} 372 1.1.1.3 christos @tab The offset in bytes to the SFrame FRE sub-section. 373 1.1 christos 374 1.1 christos @end multitable 375 1.1 christos 376 1.1 christos @menu 377 1.1.1.3 christos * SFrame ABI/arch Identifier:: 378 1.1 christos @end menu 379 1.1 christos 380 1.1.1.3 christos @node SFrame ABI/arch Identifier 381 1.1.1.3 christos @subsection SFrame ABI/arch Identifier 382 1.1.1.3 christos @cindex SFrame ABI/arch Identifier 383 1.1 christos 384 1.1 christos SFrame header identifies the ABI/arch of the target system for which the 385 1.1.1.2 christos executable and hence, the stack trace information contained in the SFrame 386 1.1.1.2 christos section, is intended. There are currently three identifiable ABI/arch values 387 1.1.1.2 christos in the format. 388 1.1 christos 389 1.1 christos @multitable {SFRAME_ABI_AARCH64_ENDIAN_LITTLE} {Value} {@code{AARCH64 little-endian}} 390 1.1 christos @headitem ABI/arch Identifier @tab Value @tab Description 391 1.1 christos 392 1.1 christos @tindex SFRAME_ABI_AARCH64_ENDIAN_BIG 393 1.1 christos @item @code{SFRAME_ABI_AARCH64_ENDIAN_BIG} 394 1.1 christos @tab 1 @tab AARCH64 big-endian 395 1.1 christos 396 1.1 christos @tindex SFRAME_ABI_AARCH64_ENDIAN_LITTLE 397 1.1 christos @item @code{SFRAME_ABI_AARCH64_ENDIAN_LITTLE} 398 1.1 christos @tab 2 @tab AARCH64 little-endian 399 1.1 christos 400 1.1 christos @tindex SFRAME_ABI_AMD64_ENDIAN_LITTLE 401 1.1 christos @item @code{SFRAME_ABI_AMD64_ENDIAN_LITTLE} 402 1.1 christos @tab 3 @tab AMD64 little-endian 403 1.1 christos 404 1.1 christos @end multitable 405 1.1 christos 406 1.1 christos The presence of an explicit identification of ABI/arch in SFrame may allow 407 1.1.1.3 christos stack trace generators to make certain ABI/arch-specific decisions. 408 1.1 christos 409 1.1 christos @node SFrame Function Descriptor Entries 410 1.1 christos @section SFrame FDE 411 1.1 christos @cindex SFrame FDE 412 1.1 christos 413 1.1.1.3 christos The SFrame function descriptor entry sub-section is an array of the 414 1.1 christos fixed-length SFrame function descriptor entries (SFrame FDEs). Each SFrame FDE 415 1.1.1.2 christos is a packed structure which contains information to describe a function's stack 416 1.1.1.2 christos trace information at a high-level. 417 1.1 christos 418 1.1.1.3 christos The array of SFrame FDEs is sorted on the @code{sfde_func_start_address} if 419 1.1.1.3 christos the SFrame section header flag @code{sfp_flags} has @code{SFRAME_F_FDE_SORTED} 420 1.1.1.3 christos set. Typically (as is the case with GNU ld) a linked object or executable 421 1.1.1.3 christos will have the @code{SFRAME_F_FDE_SORTED} set. This makes the job of a stack 422 1.1.1.3 christos tracer easier as it may then employ binary search schemes to look for the 423 1.1.1.3 christos pertinent SFrame FDE. 424 1.1.1.3 christos 425 1.1 christos @example 426 1.1 christos typedef struct sframe_func_desc_entry 427 1.1 christos @{ 428 1.1 christos int32_t sfde_func_start_address; 429 1.1 christos uint32_t sfde_func_size; 430 1.1 christos uint32_t sfde_func_start_fre_off; 431 1.1 christos uint32_t sfde_func_num_fres; 432 1.1 christos uint8_t sfde_func_info; 433 1.1.1.2 christos uint8_t sfde_func_rep_size; 434 1.1.1.2 christos uint16_t sfde_func_padding2; 435 1.1 christos @} ATTRIBUTE_PACKED sframe_func_desc_entry; 436 1.1 christos @end example 437 1.1 christos 438 1.1.1.2 christos Every element of the SFrame function descriptor entry is naturally aligned. 439 1.1.1.2 christos 440 1.1 christos @code{sfde_func_start_fre_off} is the offset to the first SFrame FRE for the 441 1.1 christos function. This offset is relative to the @emph{end of the SFrame FDE} 442 1.1.1.3 christos sub-section (unlike the sub-section offsets in the SFrame header, which are 443 1.1.1.3 christos relative to the @emph{end} of the SFrame header). 444 1.1.1.3 christos 445 1.1.1.3 christos @code{sfde_func_info} is the SFrame FDE "info word", containing information on 446 1.1.1.3 christos the FRE type and the FDE type for the function @xref{The SFrame FDE Info Word}. 447 1.1 christos 448 1.1.1.3 christos @cindex Provisions for future ABIs 449 1.1.1.3 christos Apart from the @code{sfde_func_padding2}, the SFrame FDE has some currently 450 1.1.1.3 christos unused bits in the SFrame FDE info word, @xref{The SFrame FDE Info Word}, that 451 1.1.1.3 christos may be used for the purpose of extending the SFrame file format specification 452 1.1.1.3 christos for future ABIs. 453 1.1 christos 454 1.1 christos Following table describes each component of the SFrame FDE structure: 455 1.1 christos 456 1.1.1.3 christos @multitable {Offset} {@code{uint32_t}} {@code{sfde_func_start_fre_off}} {Signed 32-bit integral field denoting the} 457 1.1.1.3 christos @headitem Offset @tab Type @tab Name @tab Description 458 1.1 christos @item 0x00 459 1.1.1.3 christos @tab @code{int32_t} 460 1.1.1.3 christos @tab @code{sfde_func_start_address} 461 1.1 christos @tab Signed 32-bit integral field denoting the virtual memory address of the 462 1.1 christos described function. 463 1.1 christos 464 1.1 christos @item 0x04 465 1.1.1.3 christos @tab @code{uint32_t} 466 1.1.1.3 christos @tab @code{sfde_func_size} 467 1.1 christos @tab Unsigned 32-bit integral field specifying the size of the function in 468 1.1 christos bytes. 469 1.1 christos 470 1.1 christos @item 0x08 471 1.1.1.3 christos @tab @code{uint32_t} 472 1.1.1.3 christos @tab @code{sfde_func_start_fre_off} 473 1.1 christos @tab Unsigned 32-bit integral field specifying the offset in bytes of the 474 1.1 christos function's first SFrame FRE in the SFrame section. 475 1.1 christos 476 1.1 christos @item 0x0c 477 1.1.1.3 christos @tab @code{uint32_t} 478 1.1.1.3 christos @tab @code{sfde_func_num_fres} 479 1.1 christos @tab Unsigned 32-bit integral field specifying the total number of SFrame FREs 480 1.1 christos used for the function. 481 1.1 christos 482 1.1 christos @item 0x10 483 1.1.1.3 christos @tab @code{uint8_t} 484 1.1.1.3 christos @tab @code{sfde_func_info} 485 1.1.1.2 christos @tab Unsigned 8-bit integral field specifying the SFrame FDE info word. 486 1.1.1.3 christos @xref{The SFrame FDE Info Word}. 487 1.1.1.2 christos 488 1.1.1.2 christos @item 0x11 489 1.1.1.3 christos @tab @code{uint8_t} 490 1.1.1.3 christos @tab @code{sfde_func_rep_size} 491 1.1.1.2 christos @tab Unsigned 8-bit integral field specifying the size of the repetitive code 492 1.1.1.2 christos block for which an SFrame FDE of type SFRAME_FDE_TYPE_PCMASK is used. For 493 1.1.1.2 christos example, in AMD64, the size of a pltN entry is 16 bytes. 494 1.1.1.2 christos 495 1.1.1.2 christos @item 0x12 496 1.1.1.3 christos @tab @code{uint16_t} 497 1.1.1.3 christos @tab @code{sfde_func_padding2} 498 1.1.1.2 christos @tab Padding of 2 bytes. Currently unused bytes. 499 1.1 christos 500 1.1 christos @end multitable 501 1.1 christos 502 1.1 christos @menu 503 1.1.1.3 christos * The SFrame FDE Info Word:: 504 1.1.1.3 christos * The SFrame FDE Types:: 505 1.1.1.3 christos * The SFrame FRE Types:: 506 1.1 christos @end menu 507 1.1 christos 508 1.1.1.3 christos @cindex The SFrame FDE Info Word 509 1.1.1.3 christos @node The SFrame FDE Info Word 510 1.1.1.3 christos @subsection The SFrame FDE Info Word 511 1.1 christos 512 1.1 christos The info word is a bitfield split into three parts. From MSB to LSB: 513 1.1 christos 514 1.1.1.2 christos @multitable {Bit offset} {@code{pauth_key}} {Specify which key is used for signing the return addresses} 515 1.1 christos @headitem Bit offset @tab Name @tab Description 516 1.1.1.2 christos @item 7--6 517 1.1 christos @tab @code{unused} 518 1.1 christos @tab Unused bits. 519 1.1 christos 520 1.1.1.2 christos @item 5 521 1.1.1.2 christos @tab @code{pauth_key} 522 1.1.1.3 christos @tab (For AARCH64) Specify which key is used for signing the return addresses 523 1.1.1.3 christos in the SFrame FDE. Two possible values: @* 524 1.1.1.2 christos SFRAME_AARCH64_PAUTH_KEY_A (0), or @* 525 1.1.1.3 christos SFRAME_AARCH64_PAUTH_KEY_B (1). @* 526 1.1.1.3 christos Ununsed in AMD64. 527 1.1.1.2 christos 528 1.1 christos @item 4 529 1.1 christos @tab @code{fdetype} 530 1.1.1.2 christos @tab Specify the SFrame FDE type. Two possible values: @* 531 1.1.1.2 christos SFRAME_FDE_TYPE_PCMASK (1), or @* 532 1.1.1.2 christos SFRAME_FDE_TYPE_PCINC (0). @* 533 1.1.1.3 christos @xref{The SFrame FDE Types}. 534 1.1 christos 535 1.1 christos @item 0--3 536 1.1 christos @tab @code{fretype} 537 1.1.1.3 christos @tab Choice of three SFrame FRE types. @xref{The SFrame FRE Types}. 538 1.1 christos @end multitable 539 1.1 christos 540 1.1.1.3 christos @node The SFrame FDE Types 541 1.1.1.3 christos @subsection The SFrame FDE Types 542 1.1 christos @tindex SFRAME_FDE_TYPE_PCMASK 543 1.1 christos @tindex SFRAME_FDE_TYPE_PCINC 544 1.1 christos 545 1.1.1.3 christos The SFrame format defines two types of FDE entries. The choice of which SFrame 546 1.1.1.3 christos FDE type to use is made based on the instruction patterns in the relevant 547 1.1.1.3 christos program stub. 548 1.1 christos 549 1.1 christos An SFrame FDE of type @code{SFRAME_FDE_TYPE_PCINC} is an indication that the PCs in the 550 1.1 christos FREs should be treated as increments in bytes. This is used fo the the bulk of 551 1.1 christos the executable code of a program, which contains instructions with no specific 552 1.1 christos pattern. 553 1.1 christos 554 1.1 christos In contrast, an SFrame FDE of type @code{SFRAME_FDE_TYPE_PCMASK} is an 555 1.1 christos indication that the PCs in the FREs should be treated as masks. This type is 556 1.1 christos useful for the cases where a small pattern of instructions in a program stub is 557 1.1 christos used repeatedly for a specific functionality. Typical usecases are pltN 558 1.1 christos entries and trampolines. 559 1.1 christos 560 1.1.1.2 christos @multitable {SFRAME_FDE_TYPE_PCMASK} {Value} {Unwinders perform a Unwinders perform a} 561 1.1 christos @headitem Name of SFrame FDE type @tab Value @tab Description 562 1.1 christos 563 1.1 christos @item SFRAME_FDE_TYPE_PCINC 564 1.1.1.3 christos @tab 0 @tab Stacktracers perform a @* 565 1.1.1.2 christos (PC >= FRE_START_ADDR) to look up a matching FRE. 566 1.1 christos 567 1.1 christos @item SFRAME_FDE_TYPE_PCMASK 568 1.1.1.3 christos @tab 1 @tab Stacktracers perform a @* 569 1.1.1.2 christos (PC % REP_BLOCK_SIZE @* 570 1.1.1.2 christos >= FRE_START_ADDR) 571 1.1.1.2 christos to look up a matching FRE. REP_BLOCK_SIZE is the size in bytes of the 572 1.1.1.3 christos repeating block of program instructions and is encoded via 573 1.1.1.3 christos @code{sfde_func_rep_size} in the SFrame FDE. 574 1.1 christos 575 1.1 christos @end multitable 576 1.1 christos 577 1.1.1.3 christos @node The SFrame FRE Types 578 1.1.1.3 christos @subsection The SFrame FRE Types 579 1.1 christos 580 1.1 christos A real world application can have functions of size big and small. SFrame 581 1.1.1.3 christos format defines three types of SFrame FRE entries to effeciently encode the 582 1.1.1.3 christos stack trace information for such a variety of function sizes. These 583 1.1.1.3 christos representations vary in the number of bits needed to encode the start address 584 1.1.1.3 christos offset in the SFrame FRE. 585 1.1 christos 586 1.1 christos The following constants are defined and used to identify the SFrame FRE types: 587 1.1 christos 588 1.1.1.3 christos @multitable {SFRAME_FRE_TYPE_ADDR1} {@code{Value}} {The start address offset (in bytes) of the} 589 1.1 christos @headitem Name @tab Value @tab Description 590 1.1 christos 591 1.1 christos @tindex SFRAME_FRE_TYPE_ADDR1 592 1.1 christos @item @code{SFRAME_FRE_TYPE_ADDR1} 593 1.1 christos @tab 0 594 1.1 christos @tab The start address offset (in bytes) of the SFrame FRE is an unsigned 595 1.1 christos 8-bit value. 596 1.1 christos 597 1.1 christos @tindex SFRAME_FRE_TYPE_ADDR2 598 1.1 christos @item @code{SFRAME_FRE_TYPE_ADDR2} 599 1.1 christos @tab 1 600 1.1 christos @tab The start address offset (in bytes) of the SFrame FRE is an unsigned 601 1.1 christos 16-bit value. 602 1.1 christos 603 1.1 christos @tindex SFRAME_FRE_TYPE_ADDR4 604 1.1 christos @item @code{SFRAME_FRE_TYPE_ADDR4} 605 1.1 christos @tab 2 606 1.1 christos @tab The start address offset (in bytes) of the SFrame FRE is an unsigned 607 1.1 christos 32-bit value. 608 1.1 christos @end multitable 609 1.1 christos 610 1.1.1.3 christos A single function must use the same type of SFrame FRE throughout. The 611 1.1.1.2 christos identifier to reflect the chosen SFrame FRE type is stored in the 612 1.1.1.3 christos @code{fretype} bits in the SFrame FDE info word, 613 1.1.1.3 christos @xref{The SFrame FDE Info Word}. 614 1.1 christos 615 1.1 christos @node SFrame Frame Row Entries 616 1.1 christos @section SFrame FRE 617 1.1 christos @cindex SFrame FRE 618 1.1 christos 619 1.1.1.3 christos The SFrame frame row entry sub-section contains the core of the stack trace 620 1.1.1.3 christos information. An SFrame frame row entry (FRE) is a self-sufficient record 621 1.1.1.3 christos containing SFrame stack trace information for a range of contiguous 622 1.1.1.3 christos (instruction) addresses, starting at the specified offset from the start of the 623 1.1.1.3 christos function. 624 1.1.1.3 christos 625 1.1.1.3 christos Each SFrame FRE encodes the stack offsets to recover the CFA, FP and RA (where 626 1.1.1.3 christos applicable) for the respective instruction addresses. To encode this 627 1.1.1.3 christos information, each SFrame FRE is followed by S*N bytes, where: 628 1.1 christos 629 1.1 christos @itemize @minus 630 1.1 christos @item 631 1.1.1.3 christos @code{S} is the size of a stack offset for the FRE, and 632 1.1 christos @item 633 1.1.1.3 christos @code{N} is the number of stack offsets in the FRE 634 1.1 christos @end itemize 635 1.1 christos 636 1.1.1.3 christos The entities @code{S}, @code{N} are encoded in the SFrame FRE info word, via 637 1.1.1.3 christos the @code{fre_offset_size} and the @code{fre_offset_count} respectively. More 638 1.1.1.3 christos information about the precise encoding and range of values for @code{S} and 639 1.1.1.3 christos @code{N} is provided later in the @xref{The SFrame FRE Info Word}. 640 1.1.1.3 christos 641 1.1.1.3 christos @cindex Provisions for future ABIs 642 1.1.1.3 christos It is important to underline here that although the canonical interpretation 643 1.1.1.3 christos of these bytes is as stack offsets (to recover CFA, FP and RA), these bytes 644 1.1.1.3 christos @emph{may} be used by future ABIs/architectures to convey other information on 645 1.1.1.3 christos a per SFrame FRE basis. 646 1.1.1.3 christos 647 1.1.1.3 christos In summary, SFrame file format, by design, supports a variable number of stack 648 1.1.1.3 christos offsets at the tail end of each SFrame FRE. To keep the SFrame file 649 1.1.1.3 christos format specification flexible yet extensible, the interpretation of the stack 650 1.1.1.3 christos offsets is ABI/arch-specific. The precise interpretation of the FRE stack 651 1.1.1.3 christos offsets in the currently supported ABIs/architectures is covered in the 652 1.1.1.3 christos ABI/arch-specific definition of the SFrame file format, 653 1.1.1.3 christos @xref{ABI/arch-specific Definition}. 654 1.1 christos 655 1.1.1.3 christos Next, the definitions of the three SFrame FRE types are as follows: 656 1.1 christos 657 1.1 christos @example 658 1.1 christos typedef struct sframe_frame_row_entry_addr1 659 1.1 christos @{ 660 1.1 christos uint8_t sfre_start_address; 661 1.1 christos sframe_fre_info sfre_info; 662 1.1 christos @} ATTRIBUTE_PACKED sframe_frame_row_entry_addr1; 663 1.1 christos @end example 664 1.1 christos 665 1.1 christos @example 666 1.1 christos typedef struct sframe_frame_row_entry_addr2 667 1.1 christos @{ 668 1.1 christos uint16_t sfre_start_address; 669 1.1 christos sframe_fre_info sfre_info; 670 1.1 christos @} ATTRIBUTE_PACKED sframe_frame_row_entry_addr2; 671 1.1 christos @end example 672 1.1 christos 673 1.1 christos @example 674 1.1 christos typedef struct sframe_frame_row_entry_addr4 675 1.1 christos @{ 676 1.1 christos uint32_t sfre_start_address; 677 1.1 christos sframe_fre_info sfre_info; 678 1.1 christos @} ATTRIBUTE_PACKED sframe_frame_row_entry_addr4; 679 1.1 christos @end example 680 1.1 christos 681 1.1.1.2 christos For ensuring compactness, SFrame frame row entries are stored unaligned on 682 1.1.1.2 christos disk. Appropriate mechanisms need to be employed, as necessary, by the 683 1.1.1.2 christos serializing and deserializing entities, if unaligned accesses need to be 684 1.1.1.2 christos avoided. 685 1.1.1.2 christos 686 1.1 christos @code{sfre_start_address} is an unsigned 8-bit/16-bit/32-bit integral field 687 1.1 christos identifies the start address of the range of program counters, for which the 688 1.1 christos SFrame FRE applies. The value encoded in the @code{sfre_start_address} field 689 1.1 christos is the offset in bytes of the start address of the SFrame FRE, from the start 690 1.1 christos address of the function. 691 1.1 christos 692 1.1.1.3 christos Further SFrame FRE types may be added in future. 693 1.1 christos 694 1.1 christos @menu 695 1.1.1.3 christos * The SFrame FRE Info Word:: 696 1.1 christos @end menu 697 1.1 christos 698 1.1.1.3 christos @cindex The SFrame FRE Info Word 699 1.1.1.3 christos @node The SFrame FRE Info Word 700 1.1.1.3 christos @subsection The SFrame FRE Info Word 701 1.1 christos 702 1.1 christos The SFrame FRE info word is a bitfield split into four parts. From MSB to LSB: 703 1.1 christos 704 1.1 christos @multitable {Bit offset} {@code{fre_cfa_base_reg_id}} {Size of stack offsets in bytes. Valid values} 705 1.1 christos @headitem Bit offset @tab Name @tab Description 706 1.1 christos @item 7 707 1.1 christos @tab @code{fre_mangled_ra_p} 708 1.1 christos @tab Indicate whether the return address is mangled with any authorization bits (signed RA). 709 1.1 christos 710 1.1 christos @item 5-6 711 1.1 christos @tab @code{fre_offset_size} 712 1.1.1.2 christos @tab Size of stack offsets in bytes. Valid values are: @* 713 1.1.1.2 christos SFRAME_FRE_OFFSET_1B, @* 714 1.1.1.2 christos SFRAME_FRE_OFFSET_2B, and @* 715 1.1.1.2 christos SFRAME_FRE_OFFSET_4B. 716 1.1 christos 717 1.1 christos @item 1-4 718 1.1 christos @tab @code{fre_offset_count} 719 1.1.1.3 christos @tab A max value of 15 is allowed. Typically, a value of upto 3 is sufficient 720 1.1.1.3 christos for most ABIs to track all three of CFA, FP and RA. 721 1.1 christos 722 1.1 christos @item 0 723 1.1 christos @tab @code{fre_cfa_base_reg_id} 724 1.1 christos @tab Distinguish between SP or FP based CFA recovery. 725 1.1 christos 726 1.1 christos @end multitable 727 1.1 christos 728 1.1 christos @multitable {SFRAME_FRE_OFFSET_4B} {@code{Value}} {All stack offsets following the fixed-length} 729 1.1 christos @headitem Name @tab Value @tab Description 730 1.1 christos 731 1.1 christos @tindex SFRAME_FRE_OFFSET_1B 732 1.1 christos @item @code{SFRAME_FRE_OFFSET_1B} 733 1.1 christos @tab 0 734 1.1 christos @tab All stack offsets following the fixed-length FRE structure are 1 byte 735 1.1 christos long. 736 1.1 christos 737 1.1 christos @tindex SFRAME_FRE_OFFSET_2B 738 1.1 christos @item @code{SFRAME_FRE_OFFSET_2B} 739 1.1 christos @tab 1 740 1.1 christos @tab All stack offsets following the fixed-length FRE structure are 2 bytes 741 1.1 christos long. 742 1.1 christos 743 1.1 christos @tindex SFRAME_FRE_OFFSET_4B 744 1.1 christos @item @code{SFRAME_FRE_OFFSET_4B} 745 1.1 christos @tab 2 746 1.1 christos @tab All stack offsets following the fixed-length FRE structure are 4 bytes 747 1.1 christos long. 748 1.1 christos 749 1.1 christos @end multitable 750 1.1 christos 751 1.1.1.3 christos @node ABI/arch-specific Definition 752 1.1.1.3 christos @chapter ABI/arch-specific Definition 753 1.1.1.3 christos @cindex ABI/arch-specific Definition 754 1.1.1.3 christos 755 1.1.1.3 christos This section covers the ABI/arch-specific definition of the SFrame file format. 756 1.1.1.3 christos 757 1.1.1.3 christos Currently, the only part of the SFrame file format definition that is 758 1.1.1.3 christos ABI/arch-specific is the interpretation of the variable number of bytes at the 759 1.1.1.3 christos tail end of each SFrame FRE. Currently, these bytes are only used for 760 1.1.1.3 christos representing stack offsets (for all the currently supported ABIs). It is 761 1.1.1.3 christos recommended to peruse this section along with @xref{SFrame Frame Row Entries} 762 1.1.1.3 christos for clarity of context. 763 1.1.1.3 christos 764 1.1.1.3 christos Future ABIs must specify the algorithm for identifying the appropriate SFrame 765 1.1.1.3 christos FRE stack offsets in this chapter. This should inevitably include the 766 1.1.1.3 christos blueprint for interpreting the variable number of bytes at the tail end of the 767 1.1.1.3 christos SFrame FRE for the specific ABI/arch. Any further provisions, e.g., using the 768 1.1.1.3 christos auxiliary SFrame header, etc., if used, must also be outlined here. 769 1.1.1.3 christos 770 1.1.1.3 christos @menu 771 1.1.1.3 christos * AMD64:: 772 1.1.1.3 christos * AArch64:: 773 1.1.1.3 christos @end menu 774 1.1.1.3 christos 775 1.1.1.3 christos @node AMD64 776 1.1.1.3 christos @section AMD64 777 1.1.1.3 christos 778 1.1.1.3 christos Irrespective of the ABI, the first stack offset is always used to locate the 779 1.1.1.3 christos CFA, by interpreting it as: CFA = @code{BASE_REG} + offset1. The 780 1.1.1.3 christos identification of the @code{BASE_REG} is done by using the 781 1.1.1.3 christos @code{fre_cfa_base_reg_id} field in the SFrame FRE info word. 782 1.1.1.3 christos 783 1.1.1.3 christos In AMD64, the return address (RA) is always saved on stack when a function 784 1.1.1.3 christos call is executed. Further, AMD64 ABI mandates that the RA be saved at a 785 1.1.1.3 christos @code{fixed offset} from the CFA when entering a new function. This means 786 1.1.1.3 christos that the RA does not need to be tracked per SFrame FRE. The fixed offset is 787 1.1.1.3 christos encoded in the SFrame file format in the field @code{sfh_cfa_fixed_ra_offset} 788 1.1.1.3 christos in the SFrame header. @xref{SFrame Header}. 789 1.1.1.3 christos 790 1.1.1.3 christos Hence, the second stack offset (in the SFrame FRE), when present, will be used 791 1.1.1.3 christos to locate the FP, by interpreting it as: FP = CFA + offset2. 792 1.1.1.3 christos 793 1.1.1.3 christos Hence, in summary: 794 1.1.1.3 christos 795 1.1.1.3 christos @multitable {Offset ID} {Interpretation in AMD64 in AMD64} 796 1.1.1.3 christos @headitem Offset ID @tab Interpretation in AMD64 797 1.1.1.3 christos @item 1 @tab CFA = @code{BASE_REG} + offset1 798 1.1.1.3 christos @item 2 @tab FP = CFA + offset2 799 1.1.1.3 christos @end multitable 800 1.1.1.3 christos 801 1.1.1.3 christos @node AArch64 802 1.1.1.3 christos @section AArch64 803 1.1.1.3 christos 804 1.1.1.3 christos Irrespective of the ABI, the first stack offset is always used to locate the 805 1.1.1.3 christos CFA, by interpreting it as: CFA = @code{BASE_REG} + offset1. The 806 1.1.1.3 christos identification of the @code{BASE_REG} is done by using the 807 1.1.1.3 christos @code{fre_cfa_base_reg_id} field in the SFrame FRE info word. 808 1.1.1.3 christos 809 1.1.1.3 christos In AARCH64, the AAPCS64 standard specifies that the Frame Record saves both FP 810 1.1.1.3 christos and LR (a.k.a the RA). However, the standard does not mandate the precise 811 1.1.1.3 christos location in the function where the frame record is created, if at all. Hence 812 1.1.1.3 christos the need to track RA in the SFrame stack trace format. As RA is being tracked 813 1.1.1.3 christos in this ABI, the second stack offset is always used to locate the RA, by 814 1.1.1.3 christos interpreting it as: RA = CFA + offset2. The third stack offset will be used to 815 1.1.1.3 christos locate the FP, by interpreting it as: FP = CFA + offset3. 816 1.1.1.3 christos 817 1.1.1.3 christos Given the nature of things, the number of stack offsets seen on AARCH64 per 818 1.1.1.3 christos SFrame FRE is either 1 or 3. 819 1.1.1.3 christos 820 1.1.1.3 christos Hence, in summary: 821 1.1.1.3 christos 822 1.1.1.3 christos @multitable {Offset ID} {Interpretation in AArch64 in X} 823 1.1.1.3 christos @headitem Offset ID @tab Interpretation in AArch64 824 1.1.1.3 christos @item 1 @tab CFA = @code{BASE_REG} + offset1 825 1.1.1.3 christos @item 2 @tab RA = CFA + offset2 826 1.1.1.3 christos @item 3 @tab FP = CFA + offset3 827 1.1.1.3 christos @end multitable 828 1.1.1.3 christos 829 1.1.1.3 christos @node Generating Stack Traces using SFrame 830 1.1.1.3 christos @appendix Generating Stack Traces using SFrame 831 1.1.1.3 christos 832 1.1.1.3 christos Using some C-like pseudocode, this section highlights how SFrame provides a 833 1.1.1.3 christos simple, fast and low-overhead mechanism to generate stack traces. Needless to 834 1.1.1.3 christos say that for generating accurate and useful stack traces, several other aspects 835 1.1.1.3 christos will need attention: finding and decoding bits of SFrame section(s) in the 836 1.1.1.3 christos program binary, symbolization of addresses, to name a few. 837 1.1.1.3 christos 838 1.1.1.3 christos In the current context, a @code{frame} is the abstract construct that 839 1.1.1.3 christos encapsulates the following information: 840 1.1.1.3 christos @itemize @minus 841 1.1.1.3 christos @item 842 1.1.1.3 christos program counter (PC), 843 1.1.1.3 christos @item 844 1.1.1.3 christos stack pointer (SP), and 845 1.1.1.3 christos @item 846 1.1.1.3 christos frame pointer (FP) 847 1.1.1.3 christos @end itemize 848 1.1.1.3 christos 849 1.1.1.3 christos With that said, establishing the first @code{frame} should be trivial: 850 1.1.1.3 christos 851 1.1.1.3 christos @example 852 1.1.1.3 christos // frame 0 853 1.1.1.3 christos frame->pc = current_IP; 854 1.1.1.3 christos frame->sp = get_reg_value (REG_SP); 855 1.1.1.3 christos frame->fp = get_reg_value (REG_FP); 856 1.1.1.3 christos @end example 857 1.1.1.3 christos 858 1.1.1.3 christos where @code{REG_SP} and @code{REG_FP} are are ABI-designated stack pointer and 859 1.1.1.3 christos frame pointer registers respectively. 860 1.1.1.3 christos 861 1.1.1.3 christos Next, given frame N, generating stack trace needs us to get frame N+1. This 862 1.1.1.3 christos can be done as follows: 863 1.1.1.3 christos 864 1.1.1.3 christos @example 865 1.1.1.3 christos // Get the PC, SP, and FP for frame N. 866 1.1.1.3 christos pc = frame->pc; 867 1.1.1.3 christos sp = frame->sp; 868 1.1.1.3 christos fp = frame->fp; 869 1.1.1.3 christos // Populate frame N+1. 870 1.1.1.3 christos int err = get_next_frame (&next_frame, pc, sp, fp); 871 1.1.1.3 christos @end example 872 1.1.1.3 christos 873 1.1.1.3 christos where given the values of the program counter, stack pointer and frame pointer 874 1.1.1.3 christos from frame N, @code{get_next_frame} populates the provided @code{next_frame} 875 1.1.1.3 christos object and returns the error code, if any. In the following pseudocode for 876 1.1.1.3 christos @code{get_next_frame}, the @code{sframe_*} functions fetch information from the 877 1.1.1.3 christos SFrame section. 878 1.1.1.3 christos 879 1.1.1.3 christos @example 880 1.1.1.3 christos fre = sframe_find_fre (pc); 881 1.1.1.3 christos if (fre) 882 1.1.1.3 christos // Whether the base register for CFA tracking is REG_FP. 883 1.1.1.3 christos base_reg_val = sframe_fre_base_reg_fp_p (fre) ? fp : sp; 884 1.1.1.3 christos // Get the CFA stack offset from the FRE. 885 1.1.1.3 christos cfa_offset = sframe_fre_get_cfa_offset (fre); 886 1.1.1.3 christos // Get the fixed RA offset or FRE stack offset as applicable. 887 1.1.1.3 christos ra_offset = sframe_fre_get_ra_offset (fre); 888 1.1.1.3 christos // Get the fixed FP offset or FRE stack offset as applicable. 889 1.1.1.3 christos fp_offset = sframe_fre_get_fp_offset (fre); 890 1.1.1.3 christos 891 1.1.1.3 christos cfa = base_reg_val + cfa_offset; 892 1.1.1.3 christos next_frame->sp = cfa; 893 1.1.1.3 christos 894 1.1.1.3 christos ra_stack_loc = cfa + ra_offset; 895 1.1.1.3 christos // Get the address stored in the stack location. 896 1.1.1.3 christos next_frame->pc = read_value (ra_stack_loc); 897 1.1.1.3 christos 898 1.1.1.3 christos if (fp_offset is VALID) 899 1.1.1.3 christos fp_stack_loc = cfa + fp_offset; 900 1.1.1.3 christos // Get the value stored in the stack location. 901 1.1.1.3 christos next_frame->fp = read_value (fp_stack_loc); 902 1.1.1.3 christos else 903 1.1.1.3 christos // Continue to use the value of fp as it has not 904 1.1.1.3 christos // been clobbered by the current frame yet. 905 1.1.1.3 christos next_frame->fp = fp; 906 1.1.1.3 christos else 907 1.1.1.3 christos ret = ERR_NO_SFRAME_FRE; 908 1.1.1.3 christos @end example 909 1.1.1.3 christos 910 1.1 christos @node Index 911 1.1 christos @unnumbered Index 912 1.1 christos 913 1.1 christos @syncodeindex tp cp 914 1.1 christos @printindex cp 915 1.1 christos 916 1.1 christos @bye 917