15ba6b03cSchristos /* Mach-O compact unwind encoding.
2*f22f0ef4Schristos    Copyright (C) 2014-2022 Free Software Foundation, Inc.
35ba6b03cSchristos 
45ba6b03cSchristos    This file is part of BFD, the Binary File Descriptor library.
55ba6b03cSchristos 
65ba6b03cSchristos    This program is free software; you can redistribute it and/or modify
75ba6b03cSchristos    it under the terms of the GNU General Public License as published by
85ba6b03cSchristos    the Free Software Foundation; either version 3 of the License, or
95ba6b03cSchristos    (at your option) any later version.
105ba6b03cSchristos 
115ba6b03cSchristos    This program is distributed in the hope that it will be useful,
125ba6b03cSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
135ba6b03cSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
145ba6b03cSchristos    GNU General Public License for more details.
155ba6b03cSchristos 
165ba6b03cSchristos    You should have received a copy of the GNU General Public License
175ba6b03cSchristos    along with this program; if not, write to the Free Software
185ba6b03cSchristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
195ba6b03cSchristos    MA 02110-1301, USA.  */
205ba6b03cSchristos 
215ba6b03cSchristos #ifndef _MACH_O_UNWIND_H
225ba6b03cSchristos #define _MACH_O_UNWIND_H
235ba6b03cSchristos 
245ba6b03cSchristos /* Encodings bits for all cpus.  */
255ba6b03cSchristos #define MACH_O_UNWIND_IS_NOT_FUNCTION_START 0x80000000
265ba6b03cSchristos #define MACH_O_UNWIND_HAS_LSDA              0x40000000
275ba6b03cSchristos #define MACH_O_UNWIND_PERSONALITY_MASK      0x30000000
285ba6b03cSchristos #define MACH_O_UNWIND_PERSONALITY_SHIFT     28
295ba6b03cSchristos 
305ba6b03cSchristos /* Encodings for x86-64.  */
315ba6b03cSchristos 
325ba6b03cSchristos /* Kind of encoding (4 bits).  */
335ba6b03cSchristos #define MACH_O_UNWIND_X86_64_MODE_MASK       0x0f000000
345ba6b03cSchristos 
355ba6b03cSchristos /* Frame is RBP based, using the standard sequence: push %rbp; mov %rsp, %rbp.
365ba6b03cSchristos    Non-volatile registers must be saved in the stack starting at %rbp-8 to
375ba6b03cSchristos    %rbp-2040 (offset is encoded in offset bits * 8).  Registers saved are
385ba6b03cSchristos    encoded in registers bits, 3 bits per register.  */
395ba6b03cSchristos #define MACH_O_UNWIND_X86_64_MODE_RBP_FRAME  0x01000000
40fa2c2dd3Schristos #define  MACH_O_UNWIND_X86_64_RBP_FRAME_REGISTERS 0x00007FFF
415ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_RBP_FRAME_OFFSET    0x00FF0000
425ba6b03cSchristos 
435ba6b03cSchristos /* Frameless function, with a small stack size.  */
445ba6b03cSchristos #define MACH_O_UNWIND_X86_64_MODE_STACK_IMMD 0x02000000
455ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_FRAMELESS_STACK_SIZE      0x00FF0000
465ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_FRAMELESS_REG_COUNT       0x00001C00
475ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_FRAMELESS_REG_PERMUTATION 0x000003FF
485ba6b03cSchristos 
495ba6b03cSchristos /* Frameless function, with a larger stack size. The stack size is the sum
505ba6b03cSchristos    of the X in subq $X,%rsp (address of X is at function + stack size bits)
515ba6b03cSchristos    and stack adjust.  */
525ba6b03cSchristos #define MACH_O_UNWIND_X86_64_MODE_STACK_IND          0x03000000
535ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_FRAMELESS_STACK_ADJUST 0x0000E000
545ba6b03cSchristos 
555ba6b03cSchristos /* Use dwarf.  */
565ba6b03cSchristos #define MACH_O_UNWIND_X86_64_MODE_DWARF      0x04000000
575ba6b03cSchristos #define  MACH_O_UNWIND_X86_64_DWARF_SECTION_OFFSET 0x00ffffff
585ba6b03cSchristos 
595ba6b03cSchristos /* Registers.  */
605ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_NONE 0
615ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_RBX 1
625ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_R12 2
635ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_R13 3
645ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_R14 4
655ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_R15 5
665ba6b03cSchristos #define MACH_O_UNWIND_X86_64_REG_RBP 6
675ba6b03cSchristos 
685ba6b03cSchristos /* Encodings for x86 (almot the same as x86-64).  */
695ba6b03cSchristos 
705ba6b03cSchristos /* Kind of encoding (4 bits).  */
715ba6b03cSchristos #define MACH_O_UNWIND_X86_MODE_MASK       0x0f000000
725ba6b03cSchristos 
735ba6b03cSchristos /* Frame is EBP based, using the standard sequence: push %ebp; mov %esp, %ebp.
745ba6b03cSchristos    Non-volatile registers must be saved in the stack starting at %ebp-4 to
755ba6b03cSchristos    %ebp-240 (offset is encoded in offset bits * 4).  Registers saved are
765ba6b03cSchristos    encoded in registers bits, 3 bits per register.  */
775ba6b03cSchristos #define MACH_O_UNWIND_X86_MODE_EBP_FRAME  0x01000000
78fa2c2dd3Schristos #define  MACH_O_UNWIND_X86_EBP_FRAME_REGISTERS 0x00007FFF
795ba6b03cSchristos #define  MACH_O_UNWIND_X86_EBP_FRAME_OFFSET    0x00FF0000
805ba6b03cSchristos 
815ba6b03cSchristos /* Frameless function, with a small stack size.  */
825ba6b03cSchristos #define MACH_O_UNWIND_X86_MODE_STACK_IMMD 0x02000000
835ba6b03cSchristos #define  MACH_O_UNWIND_X86_FRAMELESS_STACK_SIZE      0x00FF0000
845ba6b03cSchristos #define  MACH_O_UNWIND_X86_FRAMELESS_REG_COUNT       0x00001C00
855ba6b03cSchristos #define  MACH_O_UNWIND_X86_FRAMELESS_REG_PERMUTATION 0x000003FF
865ba6b03cSchristos 
875ba6b03cSchristos /* Frameless function, with a larger stack size. The stack size is the sum
885ba6b03cSchristos    of the X in subq $X,%esp (address of X is at function + stack size bits)
895ba6b03cSchristos    and stack adjust.  */
905ba6b03cSchristos #define MACH_O_UNWIND_X86_MODE_STACK_IND          0x03000000
915ba6b03cSchristos #define  MACH_O_UNWIND_X86_FRAMELESS_STACK_ADJUST 0x0000E000
925ba6b03cSchristos 
935ba6b03cSchristos /* Use dwarf.  */
945ba6b03cSchristos #define MACH_O_UNWIND_X86_MODE_DWARF      0x04000000
955ba6b03cSchristos #define  MACH_O_UNWIND_X86_DWARF_SECTION_OFFSET 0x00ffffff
965ba6b03cSchristos 
975ba6b03cSchristos /* Registers.  */
985ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_NONE 0
995ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_EBX 1
1005ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_ECX 2
1015ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_EDX 3
1025ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_EDI 4
1035ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_ESI 5
1045ba6b03cSchristos #define MACH_O_UNWIND_X86_REG_EBP 6
1055ba6b03cSchristos 
10675f9f1baSchristos /* Encodings for arm64.  */
10775f9f1baSchristos 
10875f9f1baSchristos #define MACH_O_UNWIND_ARM64_MODE_MASK		0x0f000000
10975f9f1baSchristos 
11075f9f1baSchristos /* Leaf function:  FP/LR are *not* saved, none or some non-volatile registers
11175f9f1baSchristos    are saved, stack is allocated.  The size of the frame (register saved and
11275f9f1baSchristos    memory) is encoded in STACK_SIZE in 16 byte units.  */
11375f9f1baSchristos #define MACH_O_UNWIND_ARM64_MODE_FRAMELESS	0x02000000
11475f9f1baSchristos 
11575f9f1baSchristos #define MACH_O_UNWIND_ARM64_MODE_DWARF		0x03000000
11675f9f1baSchristos 
11775f9f1baSchristos /* Standard frame: FP/LR are pushed, SP is copied to FP, then non-volatile
11875f9f1baSchristos    registers are saved.  */
11975f9f1baSchristos #define MACH_O_UNWIND_ARM64_MODE_FRAME		0x04000000
12075f9f1baSchristos 
12175f9f1baSchristos /* Registers (for FRAME).  */
12275f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_X19_X20_PAIR	0x00000001
12375f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_X21_X22_PAIR	0x00000002
12475f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_X23_X24_PAIR	0x00000004
12575f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_X25_X26_PAIR	0x00000008
12675f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_X27_X28_PAIR	0x00000010
12775f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_D8_D9_PAIR	0x00000100
12875f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_D10_D11_PAIR	0x00000200
12975f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_D12_D13_PAIR	0x00000400
13075f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAME_D14_D15_PAIR	0x00000800
13175f9f1baSchristos 
13275f9f1baSchristos #define MACH_O_UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK 0x00fff000
13375f9f1baSchristos #define MACH_O_UNWIND_ARM64_DWARF_SECTION_OFFSET 0x00ffffff
13475f9f1baSchristos 
1355ba6b03cSchristos /* Entry in object file (in __LD,__compact_unwind section).  */
1365ba6b03cSchristos 
1375ba6b03cSchristos struct mach_o_compact_unwind_32
1385ba6b03cSchristos {
1395ba6b03cSchristos   unsigned char start[4];
1405ba6b03cSchristos   unsigned char length[4];
1415ba6b03cSchristos   unsigned char encoding[4];
1425ba6b03cSchristos   unsigned char personality[4];
1435ba6b03cSchristos   unsigned char lsda[4];
1445ba6b03cSchristos };
1455ba6b03cSchristos 
1465ba6b03cSchristos struct mach_o_compact_unwind_64
1475ba6b03cSchristos {
1485ba6b03cSchristos   unsigned char start[8];
1495ba6b03cSchristos   unsigned char length[4];
1505ba6b03cSchristos   unsigned char encoding[4];
1515ba6b03cSchristos   unsigned char personality[8];
1525ba6b03cSchristos   unsigned char lsda[8];
1535ba6b03cSchristos };
1545ba6b03cSchristos 
1555ba6b03cSchristos /* Header in images (in __TEXT,__unwind_info).  */
1565ba6b03cSchristos 
1575ba6b03cSchristos #define MACH_O_UNWIND_SECTION_VERSION 1 /* Current verion in header.  */
1585ba6b03cSchristos struct mach_o_unwind_info_header
1595ba6b03cSchristos {
1605ba6b03cSchristos   unsigned char version[4];	/* Currently MACH_O_UNWIND_SECTION_VERSION. */
1615ba6b03cSchristos   unsigned char encodings_array_offset[4];
1625ba6b03cSchristos   unsigned char encodings_array_count[4];
1635ba6b03cSchristos   unsigned char personality_array_offset[4];
1645ba6b03cSchristos   unsigned char personality_array_count[4];
1655ba6b03cSchristos   unsigned char index_offset[4];
1665ba6b03cSchristos   unsigned char index_count[4];
1675ba6b03cSchristos   /* Followed by:
1685ba6b03cSchristos      - encodings array
1695ba6b03cSchristos        These are the encodings shared, for index < encoding_array_count
1705ba6b03cSchristos      - personality array
1715ba6b03cSchristos        count given by personality_array_count
1725ba6b03cSchristos      - index entries
1735ba6b03cSchristos        count given by index_count
1745ba6b03cSchristos      - lsda index entries
1755ba6b03cSchristos        last offset given by lsda offset of last index_entry.
1765ba6b03cSchristos   */
1775ba6b03cSchristos };
1785ba6b03cSchristos 
1795ba6b03cSchristos struct mach_o_unwind_index_entry
1805ba6b03cSchristos {
1815ba6b03cSchristos   unsigned char function_offset[4];
1825ba6b03cSchristos   unsigned char second_level_offset[4];
1835ba6b03cSchristos   unsigned char lsda_index_offset[4];
1845ba6b03cSchristos };
1855ba6b03cSchristos 
1865ba6b03cSchristos struct mach_o_unwind_lsda_index_entry
1875ba6b03cSchristos {
1885ba6b03cSchristos   unsigned char function_offset[4];
1895ba6b03cSchristos   unsigned char lsda_offset[4];
1905ba6b03cSchristos };
1915ba6b03cSchristos 
1925ba6b03cSchristos /* Second level index pages.  */
1935ba6b03cSchristos 
1945ba6b03cSchristos #define MACH_O_UNWIND_SECOND_LEVEL_REGULAR 2
1955ba6b03cSchristos struct mach_o_unwind_regular_second_level_page_header
1965ba6b03cSchristos {
1975ba6b03cSchristos   unsigned char kind[4];
1985ba6b03cSchristos   unsigned char entry_page_offset[2];
1995ba6b03cSchristos   unsigned char entry_count[2];
2005ba6b03cSchristos   /* Array of entries.  */
2015ba6b03cSchristos };
2025ba6b03cSchristos 
2035ba6b03cSchristos struct mach_o_unwind_regular_second_level_entry
2045ba6b03cSchristos {
2055ba6b03cSchristos   unsigned char function_offset[4];
2065ba6b03cSchristos   unsigned char encoding[4];
2075ba6b03cSchristos };
2085ba6b03cSchristos 
2095ba6b03cSchristos #define MACH_O_UNWIND_SECOND_LEVEL_COMPRESSED 3
2105ba6b03cSchristos struct mach_o_unwind_compressed_second_level_page_header
2115ba6b03cSchristos {
2125ba6b03cSchristos   unsigned char kind[4];
2135ba6b03cSchristos   unsigned char entry_page_offset[2];
2145ba6b03cSchristos   unsigned char entry_count[2];
2155ba6b03cSchristos   unsigned char encodings_offset[2];
2165ba6b03cSchristos   unsigned char encodings_count[2];
2175ba6b03cSchristos   /* Followed by entries array (one word, see below).  */
2185ba6b03cSchristos   /* Followed by (non-common) encodings array.  */
2195ba6b03cSchristos };
2205ba6b03cSchristos 
2215ba6b03cSchristos /* Compressed entries are one word, containing function offset and encoding
2225ba6b03cSchristos    index.  */
2235ba6b03cSchristos #define MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(en) \
2245ba6b03cSchristos    ((en) & 0x00FFFFFF)
2255ba6b03cSchristos #define MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(en) \
2265ba6b03cSchristos    (((en) >> 24) & 0xFF)
2275ba6b03cSchristos 
2285ba6b03cSchristos #endif /* _MACH_O_UNWIND_H */
229