| 488 | } |
| 489 | |
| 490 | static TArray<uint8_t> CreateUnwindInfoUnix(asmjit::CCFunc *func, unsigned int &functionStart) |
| 491 | { |
| 492 | using namespace asmjit; |
| 493 | |
| 494 | // Build .eh_frame: |
| 495 | // |
| 496 | // The documentation for this can be found in the DWARF standard |
| 497 | // The x64 specific details are described in "System V Application Binary Interface AMD64 Architecture Processor Supplement" |
| 498 | // |
| 499 | // See appendix D.6 "Call Frame Information Example" in the DWARF 5 spec. |
| 500 | // |
| 501 | // The CFI_Parser<A>::decodeFDE parser on the other side.. |
| 502 | // https://github.com/llvm-mirror/libunwind/blob/master/src/DwarfParser.hpp |
| 503 | |
| 504 | // Asmjit -> DWARF register id |
| 505 | int dwarfRegId[16]; |
| 506 | dwarfRegId[X86Gp::kIdAx] = 0; |
| 507 | dwarfRegId[X86Gp::kIdDx] = 1; |
| 508 | dwarfRegId[X86Gp::kIdCx] = 2; |
| 509 | dwarfRegId[X86Gp::kIdBx] = 3; |
| 510 | dwarfRegId[X86Gp::kIdSi] = 4; |
| 511 | dwarfRegId[X86Gp::kIdDi] = 5; |
| 512 | dwarfRegId[X86Gp::kIdBp] = 6; |
| 513 | dwarfRegId[X86Gp::kIdSp] = 7; |
| 514 | dwarfRegId[X86Gp::kIdR8] = 8; |
| 515 | dwarfRegId[X86Gp::kIdR9] = 9; |
| 516 | dwarfRegId[X86Gp::kIdR10] = 10; |
| 517 | dwarfRegId[X86Gp::kIdR11] = 11; |
| 518 | dwarfRegId[X86Gp::kIdR12] = 12; |
| 519 | dwarfRegId[X86Gp::kIdR13] = 13; |
| 520 | dwarfRegId[X86Gp::kIdR14] = 14; |
| 521 | dwarfRegId[X86Gp::kIdR15] = 15; |
| 522 | int dwarfRegRAId = 16; |
| 523 | int dwarfRegXmmId = 17; |
| 524 | |
| 525 | TArray<uint8_t> cieInstructions; |
| 526 | TArray<uint8_t> fdeInstructions; |
| 527 | |
| 528 | uint8_t returnAddressReg = dwarfRegRAId; |
| 529 | int stackOffset = 8; // Offset from RSP to the Canonical Frame Address (CFA) - stack position where the CALL return address is stored |
| 530 | |
| 531 | WriteDefineCFA(cieInstructions, dwarfRegId[X86Gp::kIdSp], stackOffset); |
| 532 | WriteRegisterStackLocation(cieInstructions, returnAddressReg, stackOffset); |
| 533 | |
| 534 | FuncFrameLayout layout; |
| 535 | Error error = layout.init(func->getDetail(), func->getFrameInfo()); |
| 536 | if (error != kErrorOk) |
| 537 | I_Error("FuncFrameLayout.init failed"); |
| 538 | |
| 539 | // We need a dummy emitter for instruction size calculations |
| 540 | CodeHolder code; |
| 541 | code.init(GetHostCodeInfo()); |
| 542 | X86Assembler assembler(&code); |
| 543 | X86Emitter *emitter = assembler.asEmitter(); |
| 544 | uint64_t lastOffset = 0; |
| 545 | |
| 546 | // Note: the following code must match exactly what X86Internal::emitProlog does |
| 547 |
no test coverage detected