1# Introduction 2 3Given a minidump file, the Breakpad processor produces stack traces that include 4function names and source locations. However, minidump files contain only the 5byte-by-byte contents of threads' registers and stacks, without function names 6or machine-code-to-source mapping data. The processor consults Breakpad symbol 7files for the information it needs to produce human-readable stack traces from 8the binary-only minidump file. 9 10The platform-specific symbol dumping tools parse the debugging information the 11compiler provides (whether as DWARF or STABS sections in an ELF file or as 12stand-alone PDB files), and write that information back out in the Breakpad 13symbol file format. This format is much simpler and less detailed than compiler 14debugging information, and values legibility over compactness. 15 16# Overview 17 18Breakpad symbol files are ASCII text files, with lines delimited as appropriate 19for the host platform. Each line is a _record_, divided into fields by single 20spaces; in some cases, the last field of the record can contain spaces. The 21first field is a string indicating what sort of record the line represents 22(except for line records; these are very common, making them the default saves 23space). Some fields hold decimal or hexadecimal numbers; hexadecimal numbers 24have no "0x" prefix, and use lower-case letters. 25 26Breakpad symbol files contain the following record types. With some 27restrictions, these may appear in any order. 28 29* A `MODULE` record describes the executable file or shared library from which 30 this data was derived, for use by symbol suppliers. A `MODULE' record should 31 be the first record in the file. 32 33* A `FILE` record gives a source file name, and assigns it a number by which 34 other records can refer to it. 35 36* An `INLINE_ORIGIN` record holds an inline function name for `INLINE` records 37 to refer to. 38 39* A `FUNC` record describes a function present in the source code. 40 41* An `INLINE` record describes the inline function's nest level, call site 42 line and call site source file to which the given ranges of machine code 43 should be attributed. 44 45* A line record indicates to which source file and line a given range of 46 machine code should be attributed. The line is attributed to the function 47 defined by the most recent `FUNC` record. 48 49* A `PUBLIC` record gives the address of a linker symbol. 50 51* A `STACK` record provides information necessary to produce stack traces. 52 53# `MODULE` records 54 55A `MODULE` record provides meta-information about the module the symbol file 56describes. It has the form: 57 58> `MODULE` _operatingsystem_ _architecture_ _id_ _name_ 59 60For example: `MODULE Linux x86 D3096ED481217FD4C16B29CD9BC208BA0 firefox-bin 61` These records provide meta-information about the executable or shared library 62from which this symbol file was generated. A symbol supplier might use this 63information to find the correct symbol files to use to interpret a given 64minidump, or to perform other sorts of validation. If present, a `MODULE` record 65should be the first line in the file. 66 67The fields are separated by spaces, and cannot contain spaces themselves, except 68for _name_. 69 70* The _operatingsystem_ field names the operating system on which the 71 executable or shared library was intended to run. This field should have one 72 of the following values: 73 74 | **Value** | **Meaning** | 75 |:----------|:--------------------| 76 | Linux | Linux | 77 | mac | Macintosh OSX | 78 | windows | Microsoft Windows | 79 80* The _architecture_ field indicates what processor architecture the 81 executable or shared library contains machine code for. This field should 82 have one of the following values: 83 84 | **Value** | **Instruction Set Architecture** | 85 |:----------|:---------------------------------| 86 | x86 | Intel IA-32 | 87 | x86\_64 | AMD64/Intel 64 | 88 | ppc | 32-bit PowerPC | 89 | ppc64 | 64-bit PowerPC | 90 | unknown | unknown | 91 92* The _id_ field is a sequence of hexadecimal digits that identifies the exact 93 executable or library whose contents the symbol file describes. The way in 94 which it is computed varies from platform to platform. 95 96* The _name_ field contains the base name (the final component of the 97 directory path) of the executable or library. It may contain spaces, and 98 extends to the end of the line. 99 100# `FILE` records 101 102A `FILE` record holds a source file name for other records to refer to. It has 103the form: 104 105> `FILE` _number_ _name_ 106 107For example: `FILE 2 /home/jimb/mc/in/browser/app/nsBrowserApp.cpp 108` 109 110A `FILE` record provides the name of a source file, and assigns it a number 111which other records (line records, in particular) can use to refer to that file 112name. The _number_ field is a decimal number. The _name_ field is the name of 113the file; it may contain spaces. 114 115# `INLINE_ORIGIN` records 116 117An `INLINE_ORIGIN` record holds an inline function name for `INLINE` records to 118refer to. It has the form: 119 120> `INLINE_ORIGIN` _number_ _name_ 121 122For example: `INLINE_ORIGIN 2 nsQueryInterfaceWithError::operator()(nsID const&, 123void**) const 124` 125 126An `INLINE_ORIGIN` record provides the name of an inline function, and assigns 127it a number which other records (`INLINE` records, in particular) can use to 128refer to that function name. The _number_ field is a decimal number. The _name_ 129field is the name of the inline function; it may contain spaces. 130 131# `FUNC` records 132 133A `FUNC` record describes a source-language function. It has the form: 134 135> `FUNC` _[m]_ _address_ _size_ _parameter\_size_ _name_ 136 137For example: `FUNC m c184 30 0 nsQueryInterfaceWithError::operator()(nsID const&, 138void**) const 139` 140 141The _m_ field is optional. If present it indicates that multiple symbols 142reference this function's instructions. (In which case, only one symbol name is 143mentioned within the breakpad file.) Multiple symbols referencing the same 144instructions may occur due to identical code folding by the linker. 145 146The _address_ and _size_ fields are hexadecimal numbers indicating the start 147address and length in bytes of the machine code instructions the function 148occupies. (Breakpad symbol files cannot accurately describe functions whose code 149is not contiguous.) The start address is relative to the module's load address. 150 151The _parameter\_size_ field is a hexadecimal number indicating the size, in 152bytes, of the arguments pushed on the stack for this function. Some calling 153conventions, like the Microsoft Windows `stdcall` convention, require the called 154function to pop parameters passed to it on the stack from its caller before 155returning. The stack walker uses this value, along with data from `STACK` 156records, to step from the called function's frame to the caller's frame. 157 158The _name_ field is the name of the function. In languages that use linker 159symbol name mangling like C++, this should be the source language name (the 160"unmangled" form). This field may contain spaces. 161 162# `INLINE` records 163 164An `INLINE` record describes the inline function's nest level, call site line 165and call site source file to which the given ranges of machine code should be 166attributed. It has the form: 167 168> `INLINE` _inline_nest_level_ _call_site_line_ _call_site_file_num_ 169> _origin_num_ [_address_ _size_]+ 170 171For example: `INLINE 0 10 3 4 d30 2a fa1 b 172` 173 174The _inline_nest_level_ field is a decimal number that means it's inlined at the 175function described by a previous `INLINE` record which has _inline_nest_level_ 176one less than its. In the example below, first and third `INLINE` records have 177_inline_nest_level_ 0, which means they are inlined inside the function 178described by the `FUNC` record. The second `INLINE` record has 179_inline_nest_level_ 1 means that it's inlined at the inline function described 180by first `INLINE` record. 181``` 182FUNC ... 183INLINE 0 ... 184INLINE 1 ... 185INLINE 0 ... 186``` 187 188The _call_site_line_ and _call_site_file_num_ fields are decimal numbers 189indicating where this inline function being called at. 190 191The _origin_num_ field refers to an `INLINE_ORIGIN` record that has the name 192of the inline function. 193 194The _address_ and _size_ fields are hexadecimal numbers indicating the start 195address and length in bytes of the machine code. The address is relative to the 196module's load address. There could be more than one [_address_ _size_] range 197pair, since inline functions could have discontinuous address ranges. The ranges 198of an `INLINE` record are always inside the ranges described by its parent 199record (a `FUNC` record or an `INLINE` record). 200 201The `INLINE` record is assumed to belong to the function described by the last 202preceding `FUNC` record. `INLINE` records may not appear before the first `FUNC` 203record. 204 205# Line records 206 207A line record describes the source file and line number to which a given range 208of machine code should be attributed. It has the form: 209 210> _address_ _size_ _line_ _filenum_ 211 212For example: `c184 7 59 4 213` 214 215Because they are so common, line records do not begin with a string indicating 216the record type. All other record types' names use upper-case letters; 217hexadecimal numbers, like a line record's _address_, use lower-case letters. 218 219The _address_ and _size_ fields are hexadecimal numbers indicating the start 220address and length in bytes of the machine code. The address is relative to the 221module's load address. 222 223The _line_ field is the line number to which the machine code should be 224attributed, in decimal; the first line of the source file is line number 1. The 225_filenum_ field is a decimal number appearing in a prior `FILE` record; the name 226given in that record is the source file name for the machine code. 227 228The line is assumed to belong to the function described by the last preceding 229`FUNC` record. Line records may not appear before the first `FUNC' record. 230 231No two line records in a symbol file cover the same range of addresses. However, 232there may be many line records with identical line and file numbers, as a given 233source line may contribute many non-contiguous blocks of machine code. 234 235# `PUBLIC` records 236 237A `PUBLIC` record describes a publicly visible linker symbol, such as that used 238to identify an assembly language entry point or region of memory. It has the 239form: 240 241> PUBLIC _[m]_ _address_ _parameter\_size_ _name_ 242 243For example: `PUBLIC m 2160 0 Public2_1 244` 245 246The Breakpad processor essentially treats a `PUBLIC` record as defining a 247function with no line number data and an indeterminate size: the code extends to 248the next address mentioned. If a given address is covered by both a `PUBLIC` 249record and a `FUNC` record, the processor uses the `FUNC` data. 250 251The _m_ field is optional. If present it indicates that multiple symbols 252reference this function's instructions. (In which case, only one symbol name is 253mentioned within the breakpad file.) Multiple symbols referencing the same 254instructions may occur due to identical code folding by the linker. 255 256The _address_ field is a hexadecimal number indicating the symbol's address, 257relative to the module's load address. 258 259The _parameter\_size_ field is a hexadecimal number indicating the size of the 260parameters passed to the code whose entry point the symbol marks, if known. This 261field has the same meaning as the _parameter\_size_ field of a `FUNC` record; 262see that description for more details. 263 264The _name_ field is the name of the symbol. In languages that use linker symbol 265name mangling like C++, this should be the source language name (the "unmangled" 266form). This field may contain spaces. 267 268# `STACK WIN` records 269 270Given a stack frame, a `STACK WIN` record indicates how to find the frame that 271called it. It has the form: 272 273> STACK WIN _type_ _rva_ _code\_size_ _prologue\_size_ _epilogue\_size_ 274> _parameter\_size_ _saved\_register\_size_ _local\_size_ _max\_stack\_size_ 275> _has\_program\_string_ _program\_string\_OR\_allocates\_base\_pointer_ 276 277For example: `STACK WIN 4 2170 14 1 0 0 0 0 0 1 $eip 4 + ^ = $esp $ebp 8 + = 278$ebp $ebp ^ = 279` 280 281All fields of a `STACK WIN` record, except for the last, are hexadecimal 282numbers. 283 284The _type_ field indicates what sort of stack frame data this record holds. Its 285value should be one of the values of the 286[StackFrameTypeEnum](http://msdn.microsoft.com/en-us/library/bc5207xw%28VS.100%29.aspx) 287type in Microsoft's 288[Debug Interface Access (DIA)](http://msdn.microsoft.com/en-us/library/x93ctkx8%28VS.100%29.aspx) API. 289Breakpad uses only records of type 4 (`FrameTypeFrameData`) and 0 290(`FrameTypeFPO`); it ignores others. These types differ only in whether the last 291field is an _allocates\_base\_pointer_ flag (`FrameTypeFPO`) or a program string 292(`FrameTypeFrameData`). If more than one record covers a given address, Breakpad 293prefers `FrameTypeFrameData` records over `FrameTypeFPO` records. 294 295The _rva_ and _code\_size_ fields give the starting address and length in bytes 296of the machine code covered by this record. The starting address is relative to 297the module's load address. 298 299The _prologue\_size_ and _epilogue\_size_ fields give the length, in bytes, of 300the prologue and epilogue machine code within the record's range. Breakpad does 301not use these values. 302 303The _parameter\_size_ field gives the number of argument bytes this function 304expects to have been passed. This field has the same meaning as the 305_parameter\_size_ field of a `FUNC` record; see that description for more 306details. 307 308The _saved\_register\_size_ field gives the number of bytes in the stack frame 309dedicated to preserving the values of any callee-saves registers used by this 310function. 311 312The _local\_size_ field gives the number of bytes in the stack frame dedicated 313to holding the function's local variables and temporary values. 314 315The _max\_stack\_size_ field gives the maximum number of bytes pushed on the 316stack in the frame. Breakpad does not use this value. 317 318If the _has\_program\_string_ field is zero, then the `STACK WIN` record's final 319field is an _allocates\_base\_pointer_ flag, as a hexadecimal number; this is 320expected for records whose _type_ is 0. Otherwise, the final field is a program 321string. 322 323## Interpreting a `STACK WIN` record 324 325Given the register values for a frame F, we can find the calling frame as 326follows: 327 328* If the _has\_program\_string_ field of a `STACK WIN` record is zero, then 329 the final field is _allocates\_base\_pointer_, a flag indicating whether the 330 frame uses the frame pointer register, `%ebp`, as a general-purpose 331 register. 332 * If _allocates\_base\_pointer_ is true, then `%ebp` does not point to the 333 frame's base address. Instead, 334 * Let _next\_parameter\_size_ be the parameter size of the function 335 frame F called (**not** this record's _parameter\_size_ field), or 336 zero if F is the youngest frame on the stack. You must find this 337 value in F's callee's `FUNC`, `STACK WIN`, or `PUBLIC` records. 338 * Let _frame\_size_ be the sum of the _local\_size_ field, the 339 _saved\_register\_size_ field, and _next\_parameter\_size_. > > With 340 those definitions in place, we can recover the calling frame as 341 follows: 342 * F's return address is at `%esp +`_frame\_size_, 343 * the caller's value of `%ebp` is saved at `%esp 344 +`_next\_parameter\_size_`+`_saved\_register\_size_`- 8`, and 345 * the caller's value of `%esp` just before the call instruction was 346 `%esp +`_frame\_size_`+ 4`. > > (Why do we include 347 _next\_parameter\_size_ in the sum when computing _frame\_size_ and 348 the address of the saved `%ebp`? When a function A has called a 349 function B, the arguments that A pushed for B are considered part of 350 A's stack frame: A's value for `%esp` points at the last argument 351 pushed for B. Thus, we must include the size of those arguments 352 (given by the debugging info for B) along with the size of A's 353 register save area and local variable area (given by the debugging 354 info for A) when computing the overall size of A's frame.) 355 * If _allocates\_base\_pointer_ is false, then F's function doesn't use 356 `%ebp` at all. You may recover the calling frame as above, except that 357 the caller's value of `%ebp` is the same as F's value for `%ebp`, so no 358 steps are necessary to recover it. 359* If the _has\_program\_string_ field of a `STACK WIN` record is not zero, 360 then the record's final field is a string containing a program to be 361 interpreted to recover the caller's frame. The comments in the 362 [postfix\_evaluator.h](../src/processor/postfix_evaluator.h#40) 363 header file explain the language in which the program is written. You should 364 place the following variables in the dictionary before interpreting the 365 program: 366 * `$ebp` and `$esp` should be the values of the `%ebp` and `%esp` 367 registers in F. 368 * `.cbParams`, `.cbSavedRegs`, and `.cbLocals`, should be the values of 369 the `STACK WIN` record's _parameter\_size_, _saved\_register\_size_, and 370 _local\_size_ fields. 371 * `.raSearchStart` should be set to the address on the stack to begin 372 scanning for a return address, if necessary. The Breakpad processor sets 373 this to the value of `%esp` in F, plus the _frame\_size_ value mentioned 374 above. 375 376> If the program stores values for `$eip`, `$esp`, `$ebp`, `$ebx`, `$esi`, or 377> `$edi`, then those are the values of the given registers in the caller. If the 378> value of `$eip` is zero, that indicates that the end of the stack has been 379> reached. 380 381The Breakpad processor checks that the value yielded by the above for the 382calling frame's instruction address refers to known code; if the address seems 383to be bogus, then it uses a heuristic search to find F's return address and 384stack base. 385 386# `STACK CFI` records 387 388`STACK CFI` ("Call Frame Information") records describe how to walk the stack 389when execution is at a given machine instruction. These records take one of two 390forms: 391 392> `STACK CFI INIT` _address_ _size_ _register<sub>1</sub>_: 393> _expression<sub>1</sub>_ _register<sub>2</sub>_: _expression<sub>2</sub>_ ... 394> 395> `STACK CFI` _address_ _register<sub>1</sub>_: _expression<sub>1</sub>_ 396> _register<sub>2</sub>_: _expression<sub>2</sub>_ ... 397 398For example: 399 400``` 401STACK CFI INIT 804c4b0 40 .cfa: $esp 4 + $eip: .cfa 4 - ^ 402STACK CFI 804c4b1 .cfa: $esp 8 + $ebp: .cfa 8 - ^ 403``` 404 405The _address_ and _size_ fields are hexadecimal numbers. Each 406_register_<sub>i</sub> is the name of a register or pseudoregister. Each 407_expression_ is a Breakpad postfix expression, which may contain spaces, but 408never ends with a colon. (The appropriate register names for a given 409architecture are determined when `STACK CFI` records are first enabled for that 410architecture, and should be documented in the appropriate 411`stackwalker_`_architecture_`.cc` source file.) 412 413STACK CFI records describe, at each machine instruction in a given function, how 414to recover the values the machine registers had in the function's caller. 415Naturally, some registers' values are simply lost, but there are three cases in 416which they can be recovered: 417 418* You can always recover the program counter, because that's the function's 419 return address. If the function is ever going to return, the PC must be 420 saved somewhere. 421 422* You can always recover the stack pointer. The function is responsible for 423 popping its stack frame before it returns to the caller, so it must be able 424 to restore this, as well. 425 426* You should be able to recover the values of callee-saves registers. These 427 are registers whose values the callee must preserve, either by saving them 428 in its own stack frame before using them and re-loading them before 429 returning, or by not using them at all. 430 431(As an exception, note that functions which never return may not save any of 432this data. It may not be possible to walk the stack past such functions' stack 433frames.) 434 435Given rules for recovering the values of a function's caller's registers, we can 436walk up the stack. Starting with the current set of registers --- the PC of the 437instruction we're currently executing, the current stack pointer, etc. --- we 438use CFI to recover the values those registers had in the caller of the current 439frame. This gives us a PC in the caller whose CFI we can look up; we apply the 440process again to find that function's caller; and so on. 441 442Concretely, CFI records represent a table with a row for each machine 443instruction address and a column for each register. The table entry for a given 444address and register contains a rule describing how, when the PC is at that 445address, to restore the value that register had in the caller. 446 447There are some special columns: 448 449* A column named `.cfa`, for "Canonical Frame Address", tells how to compute 450 the base address of the frame; other entries can refer to the CFA in their 451 rules. 452 453* A column named `.ra` represents the return address. 454 455For example, suppose we have a machine with 32-bit registers, one-byte 456instructions, a stack that grows downwards, and an assembly language that 457resembles C. Suppose further that we have a function whose machine code looks 458like this: 459 460``` 461func: ; entry point; return address at sp 462func+0: sp -= 16 ; allocate space for stack frame 463func+1: sp[12] = r0 ; save 4-byte r0 at sp+12 464 ... ; stuff that doesn't affect stack 465func+10: sp -= 4; *sp = x ; push some 4-byte x on the stack 466 ... ; stuff that doesn't affect stack 467func+20: r0 = sp[16] ; restore saved r0 468func+21: sp += 20 ; pop whole stack frame 469func+22: pc = *sp; sp += 4 ; pop return address and jump to it 470``` 471 472The following table would describe the function above: 473 474| **code address** | **.cfa** | **r0 (on Google Code)** | **r1 (on Google Code)** | ... | **.ra** | 475|:-----------------|:---------|:------------------------|:------------------------|:----|:---------| 476| func+0 | sp | | | | `cfa[0]` | 477| func+1 | sp+16 | | | | `cfa[0]` | 478| func+2 | sp+16 | `cfa[-4]` | | | `cfa[0]` | 479| func+11 | sp+20 | `cfa[-4]` | | | `cfa[0]` | 480| func+21 | sp+20 | | | | `cfa[0]` | 481| func+22 | sp | | | | `cfa[0]` | 482 483Some things to note here: 484 485* Each row describes the state of affairs **before** executing the instruction 486 at the given address. Thus, the row for func+0 describes the state before we 487 execute the first instruction, which allocates the stack frame. In the next 488 row, the formula for computing the CFA has changed, reflecting the 489 allocation. 490 491* The other entries are written in terms of the CFA; this allows them to 492 remain unchanged as the stack pointer gets bumped around. For example, to 493 find the caller's value for r0 (on Google Code) at func+2, we would first 494 compute the CFA by adding 16 to the sp, and then subtract four from that to 495 find the address at which r0 (on Google Code) was saved. 496 497* Although the example doesn't show this, most calling conventions designate 498 "callee-saves" and "caller-saves" registers. The callee must restore the 499 values of "callee-saves" registers before returning (if it uses them at 500 all), whereas the callee is free to use "caller-saves" registers without 501 restoring their values. A function that uses caller-saves registers 502 typically does not save their original values at all; in this case, the CFI 503 marks such registers' values as "unrecoverable". 504 505* Exactly where the CFA points in the frame --- at the return address? below 506 it? At some fixed point within the frame? --- is a question of definition 507 that depends on the architecture and ABI in use. But by definition, the CFA 508 remains constant throughout the lifetime of the frame. It's up to 509 architecture- specific code to know what significance to assign the CFA, if 510 any. 511 512To save space, the most common type of CFI record only mentions the table 513entries at which changes take place. So for the above, the CFI data would only 514actually mention the non-blank entries here: 515 516| **insn** | **cfa** | **r0 (on Google Code)** | **r1 (on Google Code)** | ... | **ra** | 517|:---------|:--------|:------------------------|:------------------------|:----|:---------| 518| func+0 | sp | | | | `cfa[0]` | 519| func+1 | sp+16 | | | | | 520| func+2 | | `cfa[-4]` | | | | 521| func+11 | sp+20 | | | | | 522| func+21 | | r0 (on Google Code) | | | | 523| func+22 | sp | | | | | 524 525A `STACK CFI INIT` record indicates that, at the machine instruction at 526_address_, belonging to some function, the value that _register<sub>n</sub>_ had 527in that function's caller can be recovered by evaluating 528_expression<sub>n</sub>_. The values of any callee-saves registers not mentioned 529are assumed to be unchanged. (`STACK CFI` records never mention caller-saves 530registers.) These rules apply starting at _address_ and continue up to, but not 531including, the address given in the next `STACK CFI` record. The _size_ field is 532the total number of bytes of machine code covered by this record and any 533subsequent `STACK CFI` records (until the next `STACK CFI INIT` record). The 534_address_ field is relative to the module's load address. 535 536A `STACK CFI` record (no `INIT`) is the same, except that it mentions only those 537registers whose recovery rules have changed from the previous CFI record. There 538must be a prior `STACK CFI INIT` or `STACK CFI` record in the symbol file. The 539_address_ field of this record must be greater than that of the previous record, 540and it must not be at or beyond the end of the range given by the most recent 541`STACK CFI INIT` record. The address is relative to the module's load address. 542 543Each expression is a breakpad-style postfix expression. Expressions may contain 544spaces, but their tokens may not end with colons. When an expression mentions a 545register, it refers to the value of that register in the callee, even if a prior 546name/expression pair gives that register's value in the caller. The exception is 547`.cfa`, which refers to the canonical frame address computed by the .cfa rule in 548force at the current instruction. 549 550The special expression `.undef` indicates that the given register's value cannot 551be recovered. 552 553The register names preceding the expressions are always followed by colons. The 554expressions themselves never contain tokens ending with colons. 555 556There are two special register names: 557 558* `.cfa` ("Canonical Frame Address") is the base address of the stack frame. 559 Other registers' rules may refer to this. If no rule is provided for the 560 stack pointer, the value of `.cfa` is the caller's stack pointer. 561 562* `.ra` is the return address. This is the value of the restored program 563 counter. We use `.ra` instead of the architecture-specific name for the 564 program counter. 565 566The Breakpad stack walker requires that there be rules in force for `.cfa` and 567`.ra` at every code address from which it unwinds. If those rules are not 568present, the stack walker will ignore the `STACK CFI` data, and try to use a 569different strategy. 570 571So the CFI for the example function above would be as follows, if `func` were at 572address 0x1000 (relative to the module's load address): 573 574``` 575STACK CFI INIT 1000 .cfa: $sp .ra: .cfa ^ 576STACK CFI 1001 .cfa: $sp 16 + 577STACK CFI 1002 $r0: .cfa 4 - ^ 578STACK CFI 100b .cfa: $sp 20 + 579STACK CFI 1015 $r0: $r0 580STACK CFI 1016 .cfa: $sp 581``` 582