mirror of
https://github.com/darlinghq/darling-libunwind.git
synced 2024-11-23 04:29:39 +00:00
Move Source From Main Repo
Based on libunwind-35.4
This commit is contained in:
commit
2708dbea23
44
CMakeLists.txt
Normal file
44
CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
||||
project(darling-libsystem_unwind)
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
enable_language(C ASM)
|
||||
|
||||
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 0)
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc -nostdinc++ -fno-rtti -fno-exceptions -funwind-tables -ggdb -O0")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3 -w -nostdinc -fno-rtti -funwind-tables -ggdb -O0")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__DARWIN_UNIX03 -fPIC -w")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib -Wl,-flat_namespace -Wl,-undefined,suppress")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
set(libunwind_sources
|
||||
src/libuwind.cxx
|
||||
src/Registers.S
|
||||
src/unw_getcontext.S
|
||||
src/UnwindLevel1.c
|
||||
src/UnwindLevel1-gcc-ext.c
|
||||
src/Unwind-sjlj.c
|
||||
)
|
||||
|
||||
set(DYLIB_INSTALL_NAME "/usr/lib/system/libunwind.dylib")
|
||||
add_circular(unwind FAT
|
||||
SOURCES
|
||||
${libunwind_sources}
|
||||
SIBLINGS
|
||||
system_c
|
||||
keymgr
|
||||
)
|
||||
#target_link_libraries(unwind PRIVATE system_c keymgr)
|
||||
#set_target_properties(unwind PROPERTIES LINKER_LANGUAGE C)
|
||||
#make_fat(unwind)
|
||||
|
||||
include(darling_static_lib)
|
||||
add_darling_static_library(unwind_static SOURCES ${libunwind_sources})
|
||||
set_target_properties(unwind_static PROPERTIES COMPILE_FLAGS "-DNDEBUG=1")
|
||||
make_fat(unwind_static)
|
||||
|
||||
install(TARGETS unwind DESTINATION libexec/darling/usr/lib/system)
|
302
include/libunwind.h
Normal file
302
include/libunwind.h
Normal file
@ -0,0 +1,302 @@
|
||||
/* -*- mode: C; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*
|
||||
* C interface to libuwind
|
||||
*
|
||||
* Source compatible with libuwind API documented at:
|
||||
* http://www.nongnu.org/libunwind/man/libunwind(3).html
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LIBUNWIND__
|
||||
#define __LIBUNWIND__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <Availability.h>
|
||||
|
||||
/* error codes */
|
||||
enum {
|
||||
UNW_ESUCCESS = 0, /* no error */
|
||||
UNW_EUNSPEC = -6540, /* unspecified (general) error */
|
||||
UNW_ENOMEM = -6541, /* out of memory */
|
||||
UNW_EBADREG = -6542, /* bad register number */
|
||||
UNW_EREADONLYREG = -6543, /* attempt to write read-only register */
|
||||
UNW_ESTOPUNWIND = -6544, /* stop unwinding */
|
||||
UNW_EINVALIDIP = -6545, /* invalid IP */
|
||||
UNW_EBADFRAME = -6546, /* bad frame */
|
||||
UNW_EINVAL = -6547, /* unsupported operation or bad value */
|
||||
UNW_EBADVERSION = -6548, /* unwind info has unsupported version */
|
||||
UNW_ENOINFO = -6549 /* no unwind info found */
|
||||
};
|
||||
|
||||
|
||||
struct unw_context_t { uint64_t data[128]; };
|
||||
typedef struct unw_context_t unw_context_t;
|
||||
|
||||
struct unw_cursor_t { uint64_t data[140]; };
|
||||
typedef struct unw_cursor_t unw_cursor_t;
|
||||
|
||||
typedef struct unw_addr_space* unw_addr_space_t;
|
||||
|
||||
typedef int unw_regnum_t;
|
||||
typedef uint64_t unw_word_t;
|
||||
typedef double unw_fpreg_t;
|
||||
|
||||
struct unw_proc_info_t
|
||||
{
|
||||
unw_word_t start_ip; /* start address of function */
|
||||
unw_word_t end_ip; /* address after end of function */
|
||||
unw_word_t lsda; /* address of language specific data area, or zero if not used */
|
||||
unw_word_t handler; /* personality routine, or zero if not used */
|
||||
unw_word_t gp; /* not used */
|
||||
unw_word_t flags; /* not used */
|
||||
uint32_t format; /* compact unwind encoding, or zero if none */
|
||||
uint32_t unwind_info_size; /* size of dwarf unwind info, or zero if none */
|
||||
unw_word_t unwind_info; /* address of dwarf unwind info, or zero if none */
|
||||
unw_word_t extra; /* mach_header of mach-o image containing function */
|
||||
};
|
||||
typedef struct unw_proc_info_t unw_proc_info_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !__arm__
|
||||
extern int unw_getcontext(unw_context_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_init_local(unw_cursor_t*, unw_context_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_step(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_get_reg(unw_cursor_t*, unw_regnum_t, unw_word_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_get_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_set_reg(unw_cursor_t*, unw_regnum_t, unw_word_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_set_fpreg(unw_cursor_t*, unw_regnum_t, unw_fpreg_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_resume(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
|
||||
extern const char* unw_regname(unw_cursor_t*, unw_regnum_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_get_proc_info(unw_cursor_t*, unw_proc_info_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_is_fpreg(unw_cursor_t*, unw_regnum_t) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_is_signal_frame(unw_cursor_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
extern int unw_get_proc_name(unw_cursor_t*, char*, size_t, unw_word_t*) __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_5_0);
|
||||
//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
|
||||
#endif
|
||||
|
||||
|
||||
#if UNW_REMOTE
|
||||
/*
|
||||
* Mac OS X "remote" API for unwinding other processes on same machine
|
||||
*
|
||||
*/
|
||||
extern unw_addr_space_t unw_local_addr_space;
|
||||
extern unw_addr_space_t unw_create_addr_space_for_task(task_t);
|
||||
extern void unw_destroy_addr_space(unw_addr_space_t);
|
||||
extern int unw_init_remote_thread(unw_cursor_t*, unw_addr_space_t, thread_t*);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* traditional libuwind "remote" API
|
||||
* NOT IMPLEMENTED on Mac OS X
|
||||
*
|
||||
* extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t, thread_t*);
|
||||
* extern unw_accessors_t unw_get_accessors(unw_addr_space_t);
|
||||
* extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int);
|
||||
* extern void unw_flush_cache(unw_addr_space_t, unw_word_t, unw_word_t);
|
||||
* extern int unw_set_caching_policy(unw_addr_space_t, unw_caching_policy_t);
|
||||
* extern void _U_dyn_register(unw_dyn_info_t*);
|
||||
* extern void _U_dyn_cancel(unw_dyn_info_t*);
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// architecture independent register numbers
|
||||
enum {
|
||||
UNW_REG_IP = -1, // instruction pointer
|
||||
UNW_REG_SP = -2, // stack pointer
|
||||
};
|
||||
|
||||
|
||||
// 32-bit x86 registers
|
||||
enum {
|
||||
UNW_X86_EAX = 0,
|
||||
UNW_X86_ECX = 1,
|
||||
UNW_X86_EDX = 2,
|
||||
UNW_X86_EBX = 3,
|
||||
UNW_X86_EBP = 4,
|
||||
UNW_X86_ESP = 5,
|
||||
UNW_X86_ESI = 6,
|
||||
UNW_X86_EDI = 7
|
||||
};
|
||||
|
||||
|
||||
// 64-bit x86_64 registers
|
||||
enum {
|
||||
UNW_X86_64_RAX = 0,
|
||||
UNW_X86_64_RDX = 1,
|
||||
UNW_X86_64_RCX = 2,
|
||||
UNW_X86_64_RBX = 3,
|
||||
UNW_X86_64_RSI = 4,
|
||||
UNW_X86_64_RDI = 5,
|
||||
UNW_X86_64_RBP = 6,
|
||||
UNW_X86_64_RSP = 7,
|
||||
UNW_X86_64_R8 = 8,
|
||||
UNW_X86_64_R9 = 9,
|
||||
UNW_X86_64_R10 = 10,
|
||||
UNW_X86_64_R11 = 11,
|
||||
UNW_X86_64_R12 = 12,
|
||||
UNW_X86_64_R13 = 13,
|
||||
UNW_X86_64_R14 = 14,
|
||||
UNW_X86_64_R15 = 15
|
||||
};
|
||||
|
||||
|
||||
// 32-bit ppc register numbers
|
||||
enum {
|
||||
UNW_PPC_R0 = 0,
|
||||
UNW_PPC_R1 = 1,
|
||||
UNW_PPC_R2 = 2,
|
||||
UNW_PPC_R3 = 3,
|
||||
UNW_PPC_R4 = 4,
|
||||
UNW_PPC_R5 = 5,
|
||||
UNW_PPC_R6 = 6,
|
||||
UNW_PPC_R7 = 7,
|
||||
UNW_PPC_R8 = 8,
|
||||
UNW_PPC_R9 = 9,
|
||||
UNW_PPC_R10 = 10,
|
||||
UNW_PPC_R11 = 11,
|
||||
UNW_PPC_R12 = 12,
|
||||
UNW_PPC_R13 = 13,
|
||||
UNW_PPC_R14 = 14,
|
||||
UNW_PPC_R15 = 15,
|
||||
UNW_PPC_R16 = 16,
|
||||
UNW_PPC_R17 = 17,
|
||||
UNW_PPC_R18 = 18,
|
||||
UNW_PPC_R19 = 19,
|
||||
UNW_PPC_R20 = 20,
|
||||
UNW_PPC_R21 = 21,
|
||||
UNW_PPC_R22 = 22,
|
||||
UNW_PPC_R23 = 23,
|
||||
UNW_PPC_R24 = 24,
|
||||
UNW_PPC_R25 = 25,
|
||||
UNW_PPC_R26 = 26,
|
||||
UNW_PPC_R27 = 27,
|
||||
UNW_PPC_R28 = 28,
|
||||
UNW_PPC_R29 = 29,
|
||||
UNW_PPC_R30 = 30,
|
||||
UNW_PPC_R31 = 31,
|
||||
UNW_PPC_F0 = 32,
|
||||
UNW_PPC_F1 = 33,
|
||||
UNW_PPC_F2 = 34,
|
||||
UNW_PPC_F3 = 35,
|
||||
UNW_PPC_F4 = 36,
|
||||
UNW_PPC_F5 = 37,
|
||||
UNW_PPC_F6 = 38,
|
||||
UNW_PPC_F7 = 39,
|
||||
UNW_PPC_F8 = 40,
|
||||
UNW_PPC_F9 = 41,
|
||||
UNW_PPC_F10 = 42,
|
||||
UNW_PPC_F11 = 43,
|
||||
UNW_PPC_F12 = 44,
|
||||
UNW_PPC_F13 = 45,
|
||||
UNW_PPC_F14 = 46,
|
||||
UNW_PPC_F15 = 47,
|
||||
UNW_PPC_F16 = 48,
|
||||
UNW_PPC_F17 = 49,
|
||||
UNW_PPC_F18 = 50,
|
||||
UNW_PPC_F19 = 51,
|
||||
UNW_PPC_F20 = 52,
|
||||
UNW_PPC_F21 = 53,
|
||||
UNW_PPC_F22 = 54,
|
||||
UNW_PPC_F23 = 55,
|
||||
UNW_PPC_F24 = 56,
|
||||
UNW_PPC_F25 = 57,
|
||||
UNW_PPC_F26 = 58,
|
||||
UNW_PPC_F27 = 59,
|
||||
UNW_PPC_F28 = 60,
|
||||
UNW_PPC_F29 = 61,
|
||||
UNW_PPC_F30 = 62,
|
||||
UNW_PPC_F31 = 63,
|
||||
UNW_PPC_MQ = 64,
|
||||
UNW_PPC_LR = 65,
|
||||
UNW_PPC_CTR = 66,
|
||||
UNW_PPC_AP = 67,
|
||||
UNW_PPC_CR0 = 68,
|
||||
UNW_PPC_CR1 = 69,
|
||||
UNW_PPC_CR2 = 70,
|
||||
UNW_PPC_CR3 = 71,
|
||||
UNW_PPC_CR4 = 72,
|
||||
UNW_PPC_CR5 = 73,
|
||||
UNW_PPC_CR6 = 74,
|
||||
UNW_PPC_CR7 = 75,
|
||||
UNW_PPC_XER = 76,
|
||||
UNW_PPC_V0 = 77,
|
||||
UNW_PPC_V1 = 78,
|
||||
UNW_PPC_V2 = 79,
|
||||
UNW_PPC_V3 = 80,
|
||||
UNW_PPC_V4 = 81,
|
||||
UNW_PPC_V5 = 82,
|
||||
UNW_PPC_V6 = 83,
|
||||
UNW_PPC_V7 = 84,
|
||||
UNW_PPC_V8 = 85,
|
||||
UNW_PPC_V9 = 86,
|
||||
UNW_PPC_V10 = 87,
|
||||
UNW_PPC_V11 = 88,
|
||||
UNW_PPC_V12 = 89,
|
||||
UNW_PPC_V13 = 90,
|
||||
UNW_PPC_V14 = 91,
|
||||
UNW_PPC_V15 = 92,
|
||||
UNW_PPC_V16 = 93,
|
||||
UNW_PPC_V17 = 94,
|
||||
UNW_PPC_V18 = 95,
|
||||
UNW_PPC_V19 = 96,
|
||||
UNW_PPC_V20 = 97,
|
||||
UNW_PPC_V21 = 98,
|
||||
UNW_PPC_V22 = 99,
|
||||
UNW_PPC_V23 = 100,
|
||||
UNW_PPC_V24 = 101,
|
||||
UNW_PPC_V25 = 102,
|
||||
UNW_PPC_V26 = 103,
|
||||
UNW_PPC_V27 = 104,
|
||||
UNW_PPC_V28 = 105,
|
||||
UNW_PPC_V29 = 106,
|
||||
UNW_PPC_V30 = 107,
|
||||
UNW_PPC_V31 = 108,
|
||||
UNW_PPC_VRSAVE = 109,
|
||||
UNW_PPC_VSCR = 110,
|
||||
UNW_PPC_SPE_ACC = 111,
|
||||
UNW_PPC_SPEFSCR = 112
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
428
include/mach-o/compact_unwind_encoding.h
Normal file
428
include/mach-o/compact_unwind_encoding.h
Normal file
@ -0,0 +1,428 @@
|
||||
/* -*- mode: C; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __COMPACT_UNWIND_ENCODING__
|
||||
#define __COMPACT_UNWIND_ENCODING__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Compilers can emit standard Dwarf FDEs in the __TEXT,__eh_frame section
|
||||
// of object files. Or compilers can emit compact unwind information in
|
||||
// the __LD,__compact_unwind section.
|
||||
//
|
||||
// When the linker creates a final linked image, it will create a
|
||||
// __TEXT,__unwind_info section. This section is a small and fast way for the
|
||||
// runtime to access unwind info for any given function. If the compiler emitted
|
||||
// compact unwind info for the function, that compact unwind info will be encoded
|
||||
// in the __TEXT,__unwind_info section. If the compiler emitted dwarf unwind info,
|
||||
// the __TEXT,__unwind_info section will contain the offset of the FDE in the
|
||||
// __TEXT,__eh_frame section in the final linked image.
|
||||
//
|
||||
// Note: Previously, the linker would transform some dwarf unwind infos into
|
||||
// compact unwind info. But that is fragile and no longer done.
|
||||
|
||||
|
||||
//
|
||||
// The compact unwind endoding is a 32-bit value which encoded in an architecture
|
||||
// specific way, which registers to restore from where, and how to unwind out
|
||||
// of the function.
|
||||
//
|
||||
typedef uint32_t compact_unwind_encoding_t;
|
||||
|
||||
|
||||
// architecture independent bits
|
||||
enum {
|
||||
UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
|
||||
UNWIND_HAS_LSDA = 0x40000000,
|
||||
UNWIND_PERSONALITY_MASK = 0x30000000,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// x86
|
||||
//
|
||||
// 1-bit: start
|
||||
// 1-bit: has lsda
|
||||
// 2-bit: personality index
|
||||
//
|
||||
// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=dwarf
|
||||
// ebp based:
|
||||
// 15-bits (5*3-bits per reg) register permutation
|
||||
// 8-bits for stack offset
|
||||
// frameless:
|
||||
// 8-bits stack size
|
||||
// 3-bits stack adjust
|
||||
// 3-bits register count
|
||||
// 10-bits register permutation
|
||||
//
|
||||
enum {
|
||||
UNWIND_X86_MODE_MASK = 0x0F000000,
|
||||
UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
|
||||
UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
|
||||
UNWIND_X86_MODE_STACK_IND = 0x03000000,
|
||||
UNWIND_X86_MODE_DWARF = 0x04000000,
|
||||
|
||||
UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
|
||||
UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
|
||||
|
||||
UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
|
||||
UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
|
||||
UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
|
||||
UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
|
||||
|
||||
UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNWIND_X86_REG_NONE = 0,
|
||||
UNWIND_X86_REG_EBX = 1,
|
||||
UNWIND_X86_REG_ECX = 2,
|
||||
UNWIND_X86_REG_EDX = 3,
|
||||
UNWIND_X86_REG_EDI = 4,
|
||||
UNWIND_X86_REG_ESI = 5,
|
||||
UNWIND_X86_REG_EBP = 6,
|
||||
};
|
||||
|
||||
//
|
||||
// For x86 there are four modes for the compact unwind encoding:
|
||||
// UNWIND_X86_MODE_EBP_FRAME:
|
||||
// EBP based frame where EBP is push on stack immediately after return address,
|
||||
// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
|
||||
// EPB value, then EBP is restored by popping off the stack, and the return
|
||||
// is done by popping the stack once more into the pc.
|
||||
// All non-volatile registers that need to be restored must have been saved
|
||||
// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4
|
||||
// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved
|
||||
// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
|
||||
// Each entry contains which register to restore.
|
||||
// UNWIND_X86_MODE_STACK_IMMD:
|
||||
// A "frameless" (EBP not used as frame pointer) function with a small
|
||||
// constant stack size. To return, a constant (encoded in the compact
|
||||
// unwind encoding) is added to the ESP. Then the return is done by
|
||||
// popping the stack into the pc.
|
||||
// All non-volatile registers that need to be restored must have been saved
|
||||
// on the stack immediately after the return address. The stack_size/4 is
|
||||
// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
|
||||
// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
|
||||
// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
|
||||
// saved and their order.
|
||||
// UNWIND_X86_MODE_STACK_IND:
|
||||
// A "frameless" (EBP not used as frame pointer) function large constant
|
||||
// stack size. This case is like the previous, except the stack size is too
|
||||
// large to encode in the compact unwind encoding. Instead it requires that
|
||||
// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
|
||||
// encoding contains the offset to the nnnnnnnn value in the function in
|
||||
// UNWIND_X86_FRAMELESS_STACK_SIZE.
|
||||
// UNWIND_X86_MODE_DWARF:
|
||||
// No compact unwind encoding is available. Instead the low 24-bits of the
|
||||
// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
|
||||
// This mode is never used in object files. It is only generated by the
|
||||
// linker in final linked images which have only dwarf unwind info for a
|
||||
// function.
|
||||
//
|
||||
// The following is the algorithm used to create the permutation encoding used
|
||||
// with frameless stacks. It is passed the number of registers to be saved and
|
||||
// an array of the register numbers saved.
|
||||
//
|
||||
//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
|
||||
//{
|
||||
// uint32_t renumregs[6];
|
||||
// for (int i=6-registerCount; i < 6; ++i) {
|
||||
// int countless = 0;
|
||||
// for (int j=6-registerCount; j < i; ++j) {
|
||||
// if ( registers[j] < registers[i] )
|
||||
// ++countless;
|
||||
// }
|
||||
// renumregs[i] = registers[i] - countless -1;
|
||||
// }
|
||||
// uint32_t permutationEncoding = 0;
|
||||
// switch ( registerCount ) {
|
||||
// case 6:
|
||||
// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
|
||||
// + 6*renumregs[2] + 2*renumregs[3]
|
||||
// + renumregs[4]);
|
||||
// break;
|
||||
// case 5:
|
||||
// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
|
||||
// + 6*renumregs[3] + 2*renumregs[4]
|
||||
// + renumregs[5]);
|
||||
// break;
|
||||
// case 4:
|
||||
// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
|
||||
// + 3*renumregs[4] + renumregs[5]);
|
||||
// break;
|
||||
// case 3:
|
||||
// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
|
||||
// + renumregs[5]);
|
||||
// break;
|
||||
// case 2:
|
||||
// permutationEncoding |= (5*renumregs[4] + renumregs[5]);
|
||||
// break;
|
||||
// case 1:
|
||||
// permutationEncoding |= (renumregs[5]);
|
||||
// break;
|
||||
// }
|
||||
// return permutationEncoding;
|
||||
//}
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// x86_64
|
||||
//
|
||||
// 1-bit: start
|
||||
// 1-bit: has lsda
|
||||
// 2-bit: personality index
|
||||
//
|
||||
// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=dwarf
|
||||
// rbp based:
|
||||
// 15-bits (5*3-bits per reg) register permutation
|
||||
// 8-bits for stack offset
|
||||
// frameless:
|
||||
// 8-bits stack size
|
||||
// 3-bits stack adjust
|
||||
// 3-bits register count
|
||||
// 10-bits register permutation
|
||||
//
|
||||
enum {
|
||||
UNWIND_X86_64_MODE_MASK = 0x0F000000,
|
||||
UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
|
||||
UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
|
||||
UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
|
||||
UNWIND_X86_64_MODE_DWARF = 0x04000000,
|
||||
|
||||
UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
|
||||
UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
|
||||
|
||||
UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
|
||||
UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
|
||||
UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
|
||||
UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
|
||||
|
||||
UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNWIND_X86_64_REG_NONE = 0,
|
||||
UNWIND_X86_64_REG_RBX = 1,
|
||||
UNWIND_X86_64_REG_R12 = 2,
|
||||
UNWIND_X86_64_REG_R13 = 3,
|
||||
UNWIND_X86_64_REG_R14 = 4,
|
||||
UNWIND_X86_64_REG_R15 = 5,
|
||||
UNWIND_X86_64_REG_RBP = 6,
|
||||
};
|
||||
//
|
||||
// For x86_64 there are four modes for the compact unwind encoding:
|
||||
// UNWIND_X86_64_MODE_RBP_FRAME:
|
||||
// RBP based frame where RBP is push on stack immediately after return address,
|
||||
// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
|
||||
// EPB value, then RBP is restored by popping off the stack, and the return
|
||||
// is done by popping the stack once more into the pc.
|
||||
// All non-volatile registers that need to be restored must have been saved
|
||||
// in a small range in the stack that starts RBP-8 to RBP-1020. The offset/4
|
||||
// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
|
||||
// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
|
||||
// Each entry contains which register to restore.
|
||||
// UNWIND_X86_64_MODE_STACK_IMMD:
|
||||
// A "frameless" (RBP not used as frame pointer) function with a small
|
||||
// constant stack size. To return, a constant (encoded in the compact
|
||||
// unwind encoding) is added to the RSP. Then the return is done by
|
||||
// popping the stack into the pc.
|
||||
// All non-volatile registers that need to be restored must have been saved
|
||||
// on the stack immediately after the return address. The stack_size/4 is
|
||||
// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 1024).
|
||||
// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
|
||||
// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
|
||||
// saved and their order.
|
||||
// UNWIND_X86_64_MODE_STACK_IND:
|
||||
// A "frameless" (RBP not used as frame pointer) function large constant
|
||||
// stack size. This case is like the previous, except the stack size is too
|
||||
// large to encode in the compact unwind encoding. Instead it requires that
|
||||
// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
|
||||
// encoding contains the offset to the nnnnnnnn value in the function in
|
||||
// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
|
||||
// UNWIND_X86_64_MODE_DWARF:
|
||||
// No compact unwind encoding is available. Instead the low 24-bits of the
|
||||
// compact encoding is the offset of the dwarf FDE in the __eh_frame section.
|
||||
// This mode is never used in object files. It is only generated by the
|
||||
// linker in final linked images which have only dwarf unwind info for a
|
||||
// function.
|
||||
//
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Relocatable Object Files: __LD,__compact_unwind
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// A compiler can generated compact unwind information for a function by adding
|
||||
// a "row" to the __LD,__compact_unwind section. This section has the
|
||||
// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
|
||||
// It is removed by the new linker, so never ends up in final executables.
|
||||
// This section is a table, initially with one row per function (that needs
|
||||
// unwind info). The table columns and some conceptual entries are:
|
||||
//
|
||||
// range-start pointer to start of function/range
|
||||
// range-length
|
||||
// compact-unwind-encoding 32-bit encoding
|
||||
// personality-function or zero if no personality function
|
||||
// lsda or zero if no LSDA data
|
||||
//
|
||||
// The length and encoding fields are 32-bits. The other are all pointer sized.
|
||||
//
|
||||
// In x86_64 assembly, these entry would look like:
|
||||
//
|
||||
// .section __LD,__compact_unwind,regular,debug
|
||||
//
|
||||
// #compact unwind for _foo
|
||||
// .quad _foo
|
||||
// .set L1,LfooEnd-_foo
|
||||
// .long L1
|
||||
// .long 0x01010001
|
||||
// .quad 0
|
||||
// .quad 0
|
||||
//
|
||||
// #compact unwind for _bar
|
||||
// .quad _bar
|
||||
// .set L2,LbarEnd-_bar
|
||||
// .long L2
|
||||
// .long 0x01020011
|
||||
// .quad __gxx_personality
|
||||
// .quad except_tab1
|
||||
//
|
||||
//
|
||||
// Notes: There is no need for any labels in the the __compact_unwind section.
|
||||
// The use of the .set directive is to force the evaluation of the
|
||||
// range-length at assembly time, instead of generating relocations.
|
||||
//
|
||||
// To support future compiler optimizations where which non-volatile registers
|
||||
// are saved changes within a function (e.g. delay saving non-volatiles until
|
||||
// necessary), there can by multiple lines in the __compact_unwind table for one
|
||||
// function, each with a different (non-overlapping) range and each with
|
||||
// different compact unwind encodings that correspond to the non-volatiles
|
||||
// saved at that range of the function.
|
||||
//
|
||||
// If a particular function is so wacky that there is no compact unwind way
|
||||
// to encode it, then the compiler can emit traditional dwarf unwind info.
|
||||
// The runtime will use which ever is available.
|
||||
//
|
||||
// Runtime support for compact unwind encodings are only available on 10.6
|
||||
// and later. So, the compiler should not generate it when targeting pre-10.6.
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Final Linked Images: __TEXT,__unwind_info
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
|
||||
// The header of the section contains a coarse index that maps function address
|
||||
// to the page (4096 byte block) containing the unwind info for that function.
|
||||
//
|
||||
|
||||
#define UNWIND_SECTION_VERSION 1
|
||||
struct unwind_info_section_header
|
||||
{
|
||||
uint32_t version; // UNWIND_SECTION_VERSION
|
||||
uint32_t commonEncodingsArraySectionOffset;
|
||||
uint32_t commonEncodingsArrayCount;
|
||||
uint32_t personalityArraySectionOffset;
|
||||
uint32_t personalityArrayCount;
|
||||
uint32_t indexSectionOffset;
|
||||
uint32_t indexCount;
|
||||
// compact_unwind_encoding_t[]
|
||||
// uintptr_t personalities[]
|
||||
// unwind_info_section_header_index_entry[]
|
||||
// unwind_info_section_header_lsda_index_entry[]
|
||||
};
|
||||
|
||||
struct unwind_info_section_header_index_entry
|
||||
{
|
||||
uint32_t functionOffset;
|
||||
uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page
|
||||
uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range
|
||||
};
|
||||
|
||||
struct unwind_info_section_header_lsda_index_entry
|
||||
{
|
||||
uint32_t functionOffset;
|
||||
uint32_t lsdaOffset;
|
||||
};
|
||||
|
||||
//
|
||||
// There are two kinds of second level index pages: regular and compressed.
|
||||
// A compressed page can hold up to 1021 entries, but it cannot be used
|
||||
// if too many different encoding types are used. The regular page holds
|
||||
// 511 entries.
|
||||
//
|
||||
|
||||
struct unwind_info_regular_second_level_entry
|
||||
{
|
||||
uint32_t functionOffset;
|
||||
compact_unwind_encoding_t encoding;
|
||||
};
|
||||
|
||||
#define UNWIND_SECOND_LEVEL_REGULAR 2
|
||||
struct unwind_info_regular_second_level_page_header
|
||||
{
|
||||
uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
|
||||
uint16_t entryPageOffset;
|
||||
uint16_t entryCount;
|
||||
// entry array
|
||||
};
|
||||
|
||||
#define UNWIND_SECOND_LEVEL_COMPRESSED 3
|
||||
struct unwind_info_compressed_second_level_page_header
|
||||
{
|
||||
uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
|
||||
uint16_t entryPageOffset;
|
||||
uint16_t entryCount;
|
||||
uint16_t encodingsPageOffset;
|
||||
uint16_t encodingsCount;
|
||||
// 32-bit entry array
|
||||
// encodings array
|
||||
};
|
||||
|
||||
#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
|
||||
#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
232
include/unwind.h
Normal file
232
include/unwind.h
Normal file
@ -0,0 +1,232 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2010-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*
|
||||
* C interface to libuwind
|
||||
*
|
||||
* Source compatible with Level 1 Base ABI documented at:
|
||||
* http://www.codesourcery.com/public/cxx-abi/abi-eh.html
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UNWIND_H__
|
||||
#define __UNWIND_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <Availability.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
_URC_NO_REASON = 0,
|
||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||
_URC_FATAL_PHASE2_ERROR = 2,
|
||||
_URC_FATAL_PHASE1_ERROR = 3,
|
||||
_URC_NORMAL_STOP = 4,
|
||||
_URC_END_OF_STACK = 5,
|
||||
_URC_HANDLER_FOUND = 6,
|
||||
_URC_INSTALL_CONTEXT = 7,
|
||||
_URC_CONTINUE_UNWIND = 8
|
||||
} _Unwind_Reason_Code;
|
||||
|
||||
typedef enum {
|
||||
_UA_SEARCH_PHASE = 1,
|
||||
_UA_CLEANUP_PHASE = 2,
|
||||
_UA_HANDLER_FRAME = 4,
|
||||
_UA_FORCE_UNWIND = 8,
|
||||
_UA_END_OF_STACK = 16 // gcc extension to C++ ABI
|
||||
} _Unwind_Action;
|
||||
|
||||
|
||||
struct _Unwind_Context; // opaque
|
||||
struct _Unwind_Exception; // forward declaration
|
||||
|
||||
struct _Unwind_Exception {
|
||||
uint64_t exception_class;
|
||||
void (*exception_cleanup)(_Unwind_Reason_Code reason, struct _Unwind_Exception* exc);
|
||||
uintptr_t private_1; // non-zero means forced unwind
|
||||
uintptr_t private_2; // holds sp that phase1 found for phase2 to use
|
||||
#if !__LP64__
|
||||
// The gcc implementation of _Unwind_Exception used attribute mode on the above fields
|
||||
// which had the side effect of causing this whole struct to round up to 32 bytes in size.
|
||||
// To be more explicit, we add pad fields added for binary compatibility.
|
||||
uint32_t reserved[3];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
|
||||
(int version,
|
||||
_Unwind_Action actions,
|
||||
uint64_t exceptionClass,
|
||||
struct _Unwind_Exception* exceptionObject,
|
||||
struct _Unwind_Context* context,
|
||||
void* stop_parameter );
|
||||
|
||||
|
||||
typedef _Unwind_Reason_Code (*__personality_routine)
|
||||
(int version,
|
||||
_Unwind_Action actions,
|
||||
uint64_t exceptionClass,
|
||||
struct _Unwind_Exception* exceptionObject,
|
||||
struct _Unwind_Context* context);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// The following are the base functions documented by the C++ ABI
|
||||
//
|
||||
#if __arm__
|
||||
extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object);
|
||||
extern void _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object);
|
||||
#else
|
||||
extern _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object);
|
||||
extern void _Unwind_Resume(struct _Unwind_Exception* exception_object);
|
||||
#endif
|
||||
extern void _Unwind_DeleteException(struct _Unwind_Exception* exception_object);
|
||||
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index);
|
||||
extern void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value);
|
||||
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context* context);
|
||||
extern void _Unwind_SetIP(struct _Unwind_Context*, uintptr_t new_value);
|
||||
extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context);
|
||||
extern uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context);
|
||||
#if __arm__
|
||||
extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter );
|
||||
#else
|
||||
extern _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter );
|
||||
#endif
|
||||
|
||||
#if __arm__
|
||||
typedef struct _Unwind_FunctionContext* _Unwind_FunctionContext_t;
|
||||
extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
|
||||
extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
|
||||
#endif
|
||||
|
||||
//
|
||||
// The following are semi-suppoted extensions to the C++ ABI
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// called by __cxa_rethrow().
|
||||
//
|
||||
#if __arm__
|
||||
extern _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object);
|
||||
#else
|
||||
extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object);
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the
|
||||
// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack
|
||||
// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON.
|
||||
//
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context*, void*);
|
||||
extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void*);
|
||||
|
||||
|
||||
//
|
||||
// _Unwind_GetCFA is a gcc extension that can be called from within a personality
|
||||
// handler to get the CFA (stack pointer before call) of current frame.
|
||||
//
|
||||
extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context*);
|
||||
|
||||
|
||||
//
|
||||
// _Unwind_GetIPInfo is a gcc extension that can be called from within a personality
|
||||
// handler. Similar to _Unwind_GetIP() but also returns in *ipBefore a non-zero
|
||||
// value if the instruction pointer is at or before the instruction causing
|
||||
// the unwind. Normally, in a function call, the IP returned is the return address
|
||||
// which is after the call instruction and may be past the end of the function
|
||||
// containing the call instruction.
|
||||
//
|
||||
extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore);
|
||||
|
||||
|
||||
//
|
||||
// __register_frame() is used with dynamically generated code to register the FDE
|
||||
// for a generated (JIT) code. The FDE must use pc-rel addressing to point to its
|
||||
// function and optional LSDA. __register_frame() has existed in all versions of
|
||||
// Mac OS X, but in 10.4 and 10.5 it was buggy and did not actually register the
|
||||
// FDE with the unwinder. In 10.6 and later it does register properly.
|
||||
//
|
||||
extern void __register_frame(const void* fde);
|
||||
extern void __deregister_frame(const void* fde);
|
||||
|
||||
|
||||
//
|
||||
// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
|
||||
// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind info"
|
||||
// which the runtime uses in preference to dwarf unwind info. This function
|
||||
// will only work if the target function has an FDE but no compact unwind info.
|
||||
//
|
||||
struct dwarf_eh_bases
|
||||
{
|
||||
uintptr_t tbase;
|
||||
uintptr_t dbase;
|
||||
uintptr_t func;
|
||||
};
|
||||
extern const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases*);
|
||||
|
||||
|
||||
//
|
||||
// This function attempts to find the start (address of first instruction) of
|
||||
// a function given an address inside the function. It only works if the function
|
||||
// has an FDE (dwarf unwind info).
|
||||
// This function is unimplemented on Mac OS X 10.6 and later. Instead, use
|
||||
// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
|
||||
extern void* _Unwind_FindEnclosingFunction(void* pc);
|
||||
|
||||
|
||||
// Mac OS X does not support text-rel and data-rel addressing so these functions are unimplemented
|
||||
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context) __attribute__((unavailable));
|
||||
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context) __attribute__((unavailable));
|
||||
|
||||
|
||||
|
||||
// Mac OS X 10.4 and 10.5 had implementations of these functions in libgcc_s.dylib,
|
||||
// but they never worked. These functions are no longer available.
|
||||
extern void __register_frame_info_bases(const void* fde, void* ob, void* tb, void* db) __attribute__((unavailable));
|
||||
extern void __register_frame_info(const void* fde, void* ob) __attribute__((unavailable));
|
||||
extern void __register_frame_info_table_bases(const void* fde, void* ob,void* tb, void* db) __attribute__((unavailable));
|
||||
extern void __register_frame_info_table(const void* fde, void* ob) __attribute__((unavailable));
|
||||
extern void __register_frame_table(const void* fde) __attribute__((unavailable));
|
||||
extern void* __deregister_frame_info(const void* fde) __attribute__((unavailable));
|
||||
extern void* __deregister_frame_info_bases(const void* fde) __attribute__((unavailable));
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // __UNWIND_H__
|
||||
|
||||
|
27
libunwind.order
Normal file
27
libunwind.order
Normal file
@ -0,0 +1,27 @@
|
||||
__Unwind_RaiseException
|
||||
_unw_getcontext
|
||||
_unw_init_local
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE24setInfoBasedOnIPRegisterEb
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE6getRegEi
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE33getInfoFromCompactEncodingSectionEyyy
|
||||
_unw_step
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE4stepEv
|
||||
x86_64:__ZN9libunwind22CompactUnwinder_x86_64INS_17LocalAddressSpaceEE23stepWithCompactEncodingEjyRS1_RNS_16Registers_x86_64E
|
||||
x86_64:__ZN9libunwind22CompactUnwinder_x86_64INS_17LocalAddressSpaceEE31stepWithCompactEncodingRBPFrameEjyRS1_RNS_16Registers_x86_64E
|
||||
_unw_get_proc_info
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE7getInfoEP15unw_proc_info_t
|
||||
__Unwind_GetLanguageSpecificData
|
||||
__Unwind_GetRegionStart
|
||||
__Unwind_GetIP
|
||||
_unw_get_reg
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE8validRegEi
|
||||
_unwind_phase2
|
||||
__Unwind_SetGR
|
||||
_unw_set_reg
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE6setRegEiy
|
||||
__Unwind_SetIP
|
||||
_unw_resume
|
||||
x86_64:__ZN9libunwind12UnwindCursorINS_17LocalAddressSpaceENS_16Registers_x86_64EE6jumptoEv
|
||||
x86_64:__ZN9libunwind16Registers_x86_646jumptoEv
|
||||
__Unwind_DeleteException
|
||||
|
546
libunwind.xcodeproj/project.pbxproj
Normal file
546
libunwind.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,546 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 45;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
F93A98ED0EC91269000D227E /* all */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = F93A98F70EC91298000D227E /* Build configuration list for PBXAggregateTarget "all" */;
|
||||
buildPhases = (
|
||||
F97377A8133A82A600BDE64E /* Simulator clean up */,
|
||||
);
|
||||
dependencies = (
|
||||
F992F1FB11A35E2F0008F9B0 /* PBXTargetDependency */,
|
||||
F93A98F50EC9127A000D227E /* PBXTargetDependency */,
|
||||
);
|
||||
name = all;
|
||||
productName = macosx;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
F9276EFD0E6E0B6100B731C9 /* libuwind.cxx in Sources */ = {isa = PBXBuildFile; fileRef = F98BEABC0D121A4000F298D0 /* libuwind.cxx */; };
|
||||
F9276EFE0E6E0B6100B731C9 /* UnwindLevel1.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C4CC60DC0145500EE1253 /* UnwindLevel1.c */; };
|
||||
F9276F000E6E0B6100B731C9 /* Registers.s in Sources */ = {isa = PBXBuildFile; fileRef = F98BEA710D10CC1700F298D0 /* Registers.s */; };
|
||||
F9276F010E6E0B6100B731C9 /* unw_getcontext.s in Sources */ = {isa = PBXBuildFile; fileRef = F98BEA4B0D10C13500F298D0 /* unw_getcontext.s */; };
|
||||
F9276F280E6E0D1400B731C9 /* UnwindLevel1-gcc-ext.c in Sources */ = {isa = PBXBuildFile; fileRef = F903E4D70DC16974007E8D28 /* UnwindLevel1-gcc-ext.c */; };
|
||||
F92A25C413C69AEE008F010E /* libunwind.h in install usr-include */ = {isa = PBXBuildFile; fileRef = F98BE9080D0F3D7D00F298D0 /* libunwind.h */; };
|
||||
F92A25C513C69AEE008F010E /* unwind.h in install usr-include */ = {isa = PBXBuildFile; fileRef = F9ABAAA91118B2BB00A06182 /* unwind.h */; };
|
||||
F92A25C913C69B39008F010E /* compact_unwind_encoding.h in install usr-include-mach-o */ = {isa = PBXBuildFile; fileRef = F9BFF9C60DC935360077A618 /* compact_unwind_encoding.h */; };
|
||||
F938B7C70F97F50D0096ACC8 /* Unwind-sjlj.c in Sources */ = {isa = PBXBuildFile; fileRef = F938B7C50F97F50D0096ACC8 /* Unwind-sjlj.c */; };
|
||||
F95A3D8B0DE3A8AA004B72E5 /* libuwind.cxx in Sources */ = {isa = PBXBuildFile; fileRef = F98BEABC0D121A4000F298D0 /* libuwind.cxx */; settings = {COMPILER_FLAGS = "-fno-exceptions"; }; };
|
||||
F95A3D8C0DE3A8AA004B72E5 /* Registers.s in Sources */ = {isa = PBXBuildFile; fileRef = F98BEA710D10CC1700F298D0 /* Registers.s */; };
|
||||
F95A3D8D0DE3A8AA004B72E5 /* unw_getcontext.s in Sources */ = {isa = PBXBuildFile; fileRef = F98BEA4B0D10C13500F298D0 /* unw_getcontext.s */; };
|
||||
F95A3D8E0DE3A8AA004B72E5 /* UnwindLevel1.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C4CC60DC0145500EE1253 /* UnwindLevel1.c */; };
|
||||
F95A3D8F0DE3A8AA004B72E5 /* UnwindLevel1-gcc-ext.c in Sources */ = {isa = PBXBuildFile; fileRef = F903E4D70DC16974007E8D28 /* UnwindLevel1-gcc-ext.c */; };
|
||||
F98F98F311A47E2C00D21E1F /* Unwind-sjlj.c in Sources */ = {isa = PBXBuildFile; fileRef = F938B7C50F97F50D0096ACC8 /* Unwind-sjlj.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
F93A98F40EC9127A000D227E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F9276EFA0E6E0B6100B731C9;
|
||||
remoteInfo = "dyld-libunwind";
|
||||
};
|
||||
F992F1FA11A35E2F0008F9B0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F95A3D890DE3A8AA004B72E5;
|
||||
remoteInfo = "libunwind-system";
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
F92A25CA13C69B62008F010E /* install usr-include */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 8;
|
||||
dstPath = "$(INSTALL_PATH_PREFIX)/usr/include";
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
F92A25C413C69AEE008F010E /* libunwind.h in install usr-include */,
|
||||
F92A25C513C69AEE008F010E /* unwind.h in install usr-include */,
|
||||
);
|
||||
name = "install usr-include";
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
F92A25CB13C69B62008F010E /* install usr-include-mach-o */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 8;
|
||||
dstPath = "$(INSTALL_PATH_PREFIX)/usr/include/mach-o";
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
F92A25C913C69B39008F010E /* compact_unwind_encoding.h in install usr-include-mach-o */,
|
||||
);
|
||||
name = "install usr-include-mach-o";
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
F903E4D70DC16974007E8D28 /* UnwindLevel1-gcc-ext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "UnwindLevel1-gcc-ext.c"; path = "src/UnwindLevel1-gcc-ext.c"; sourceTree = "<group>"; };
|
||||
F9276F140E6E0B6100B731C9 /* libunwind.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libunwind.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F92C4CC60DC0145500EE1253 /* UnwindLevel1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = UnwindLevel1.c; path = src/UnwindLevel1.c; sourceTree = "<group>"; };
|
||||
F938B7C50F97F50D0096ACC8 /* Unwind-sjlj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "Unwind-sjlj.c"; path = "src/Unwind-sjlj.c"; sourceTree = "<group>"; };
|
||||
F94138D00D1C7AC600B5EA0C /* dwarf2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2.h; path = src/dwarf2.h; sourceTree = "<group>"; };
|
||||
F94139850D25A12200B5EA0C /* UnwindCursor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = UnwindCursor.hpp; path = src/UnwindCursor.hpp; sourceTree = "<group>"; };
|
||||
F9413A530D25D7E100B5EA0C /* AddressSpace.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AddressSpace.hpp; path = src/AddressSpace.hpp; sourceTree = "<group>"; };
|
||||
F9413A540D25D7E100B5EA0C /* Registers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Registers.hpp; path = src/Registers.hpp; sourceTree = "<group>"; };
|
||||
F95A3D950DE3A8AA004B72E5 /* libunwind.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libunwind.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F95BE2990D2EB9EA007E3672 /* DwarfInstructions.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = DwarfInstructions.hpp; path = src/DwarfInstructions.hpp; sourceTree = "<group>"; };
|
||||
F95BE31A0D2EED80007E3672 /* CompactUnwinder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CompactUnwinder.hpp; path = src/CompactUnwinder.hpp; sourceTree = "<group>"; };
|
||||
F95BE4DC0D343AB9007E3672 /* DwarfParser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = DwarfParser.hpp; path = src/DwarfParser.hpp; sourceTree = "<group>"; };
|
||||
F95DF59A0DEDD12800B8DA7A /* InternalMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InternalMacros.h; path = src/InternalMacros.h; sourceTree = "<group>"; };
|
||||
F98BE9080D0F3D7D00F298D0 /* libunwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libunwind.h; path = include/libunwind.h; sourceTree = "<group>"; };
|
||||
F98BEA4B0D10C13500F298D0 /* unw_getcontext.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = unw_getcontext.s; path = src/unw_getcontext.s; sourceTree = "<group>"; };
|
||||
F98BEA710D10CC1700F298D0 /* Registers.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = Registers.s; path = src/Registers.s; sourceTree = "<group>"; };
|
||||
F98BEABC0D121A4000F298D0 /* libuwind.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = libuwind.cxx; path = src/libuwind.cxx; sourceTree = "<group>"; };
|
||||
F98BEAC40D121B7800F298D0 /* FileAbstraction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = FileAbstraction.hpp; path = src/FileAbstraction.hpp; sourceTree = "<group>"; };
|
||||
F98F98E311A475B300D21E1F /* libunwind.order */ = {isa = PBXFileReference; explicitFileType = sourcecode.exports; fileEncoding = 4; path = libunwind.order; sourceTree = "<group>"; };
|
||||
F9AB4BC61194E18500F870C2 /* libunwind_priv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libunwind_priv.h; path = src/libunwind_priv.h; sourceTree = "<group>"; };
|
||||
F9ABAAA91118B2BB00A06182 /* unwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unwind.h; path = include/unwind.h; sourceTree = "<group>"; };
|
||||
F9BFF9C60DC935360077A618 /* compact_unwind_encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = compact_unwind_encoding.h; path = "include/mach-o/compact_unwind_encoding.h"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
F95A3D900DE3A8AA004B72E5 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08FB7794FE84155DC02AAC07 /* libunwind */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F90DFABC0D8A1E9B003302A1 /* include */,
|
||||
08FB7795FE84155DC02AAC07 /* src */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
);
|
||||
name = libunwind;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB7795FE84155DC02AAC07 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9413A530D25D7E100B5EA0C /* AddressSpace.hpp */,
|
||||
F95BE31A0D2EED80007E3672 /* CompactUnwinder.hpp */,
|
||||
F94138D00D1C7AC600B5EA0C /* dwarf2.h */,
|
||||
F95BE4DC0D343AB9007E3672 /* DwarfParser.hpp */,
|
||||
F95BE2990D2EB9EA007E3672 /* DwarfInstructions.hpp */,
|
||||
F98BEAC40D121B7800F298D0 /* FileAbstraction.hpp */,
|
||||
F95DF59A0DEDD12800B8DA7A /* InternalMacros.h */,
|
||||
F98BEABC0D121A4000F298D0 /* libuwind.cxx */,
|
||||
F9AB4BC61194E18500F870C2 /* libunwind_priv.h */,
|
||||
F9413A540D25D7E100B5EA0C /* Registers.hpp */,
|
||||
F98BEA710D10CC1700F298D0 /* Registers.s */,
|
||||
F98BEA4B0D10C13500F298D0 /* unw_getcontext.s */,
|
||||
F94139850D25A12200B5EA0C /* UnwindCursor.hpp */,
|
||||
F938B7C50F97F50D0096ACC8 /* Unwind-sjlj.c */,
|
||||
F92C4CC60DC0145500EE1253 /* UnwindLevel1.c */,
|
||||
F903E4D70DC16974007E8D28 /* UnwindLevel1-gcc-ext.c */,
|
||||
F98F98E311A475B300D21E1F /* libunwind.order */,
|
||||
);
|
||||
name = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F95A3D950DE3A8AA004B72E5 /* libunwind.dylib */,
|
||||
F9276F140E6E0B6100B731C9 /* libunwind.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F90DFABC0D8A1E9B003302A1 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F9BFF9C60DC935360077A618 /* compact_unwind_encoding.h */,
|
||||
F9ABAAA91118B2BB00A06182 /* unwind.h */,
|
||||
F98BE9080D0F3D7D00F298D0 /* libunwind.h */,
|
||||
);
|
||||
name = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
F9276EFA0E6E0B6100B731C9 /* dyld-libunwind.a */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F9276F110E6E0B6100B731C9 /* Build configuration list for PBXNativeTarget "dyld-libunwind.a" */;
|
||||
buildPhases = (
|
||||
F9276EFC0E6E0B6100B731C9 /* Sources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "dyld-libunwind.a";
|
||||
productName = libunwind;
|
||||
productReference = F9276F140E6E0B6100B731C9 /* libunwind.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
F95A3D890DE3A8AA004B72E5 /* libunwind.dylib */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F95A3D920DE3A8AA004B72E5 /* Build configuration list for PBXNativeTarget "libunwind.dylib" */;
|
||||
buildPhases = (
|
||||
F95A3D8A0DE3A8AA004B72E5 /* Sources */,
|
||||
F95A3D900DE3A8AA004B72E5 /* Frameworks */,
|
||||
F92A25CA13C69B62008F010E /* install usr-include */,
|
||||
F92A25CB13C69B62008F010E /* install usr-include-mach-o */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = libunwind.dylib;
|
||||
productName = libunwind;
|
||||
productReference = F95A3D950DE3A8AA004B72E5 /* libunwind.dylib */;
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "libunwind" */;
|
||||
compatibilityVersion = "Xcode 3.0";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
Japanese,
|
||||
French,
|
||||
German,
|
||||
);
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* libunwind */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
F93A98ED0EC91269000D227E /* all */,
|
||||
F9276EFA0E6E0B6100B731C9 /* dyld-libunwind.a */,
|
||||
F95A3D890DE3A8AA004B72E5 /* libunwind.dylib */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
F97377A8133A82A600BDE64E /* Simulator clean up */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 8;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Simulator clean up";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [ \"${PLATFORM_NAME}\" == \"iphonesimulator\" ]\nthen\n # when simulator runs on 10.7 only, we can stop deleting usr/lib/system/libunwind.dylib\n rm -rf \"${DSTROOT}/usr\"\n rm -rf \"${DSTROOT}/$SDKROOT/usr/local\"\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
F9276EFC0E6E0B6100B731C9 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F9276EFD0E6E0B6100B731C9 /* libuwind.cxx in Sources */,
|
||||
F938B7C70F97F50D0096ACC8 /* Unwind-sjlj.c in Sources */,
|
||||
F9276EFE0E6E0B6100B731C9 /* UnwindLevel1.c in Sources */,
|
||||
F9276F280E6E0D1400B731C9 /* UnwindLevel1-gcc-ext.c in Sources */,
|
||||
F9276F000E6E0B6100B731C9 /* Registers.s in Sources */,
|
||||
F9276F010E6E0B6100B731C9 /* unw_getcontext.s in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F95A3D8A0DE3A8AA004B72E5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F95A3D8B0DE3A8AA004B72E5 /* libuwind.cxx in Sources */,
|
||||
F95A3D8C0DE3A8AA004B72E5 /* Registers.s in Sources */,
|
||||
F95A3D8D0DE3A8AA004B72E5 /* unw_getcontext.s in Sources */,
|
||||
F95A3D8E0DE3A8AA004B72E5 /* UnwindLevel1.c in Sources */,
|
||||
F95A3D8F0DE3A8AA004B72E5 /* UnwindLevel1-gcc-ext.c in Sources */,
|
||||
F98F98F311A47E2C00D21E1F /* Unwind-sjlj.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
F93A98F50EC9127A000D227E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F9276EFA0E6E0B6100B731C9 /* dyld-libunwind.a */;
|
||||
targetProxy = F93A98F40EC9127A000D227E /* PBXContainerItemProxy */;
|
||||
};
|
||||
F992F1FB11A35E2F0008F9B0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F95A3D890DE3A8AA004B72E5 /* libunwind.dylib */;
|
||||
targetProxy = F992F1FA11A35E2F0008F9B0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1DEB914F08733D8E0010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
USE_HEADERMAP = NO;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB915008733D8E0010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
USE_HEADERMAP = NO;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F9276F120E6E0B6100B731C9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
i386,
|
||||
x86_64,
|
||||
ppc,
|
||||
);
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||
GCC_ENABLE_CPP_RTTI = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = FOR_DYLD;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
|
||||
GCC_WARN_MISSING_PARENTHESES = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = NO;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
|
||||
OTHER_CFLAGS = "-fexceptions";
|
||||
OTHER_CPLUSPLUSFLAGS = "-funwind-tables";
|
||||
PRODUCT_NAME = unwind;
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F9276F130E6E0B6100B731C9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||
GCC_ENABLE_CPP_RTTI = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 3;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
FOR_DYLD,
|
||||
NDEBUG,
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
|
||||
INSTALL_PATH = /usr/local/lib/dyld;
|
||||
OTHER_CFLAGS = "-fexceptions";
|
||||
OTHER_CPLUSPLUSFLAGS = "-funwind-tables";
|
||||
PRODUCT_NAME = unwind;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F93A98EE0EC91269000D227E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
PRODUCT_NAME = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F93A98EF0EC91269000D227E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
PRODUCT_NAME = macosx;
|
||||
ZERO_LINK = NO;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F95A3D930DE3A8AA004B72E5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
x86_64,
|
||||
i386,
|
||||
);
|
||||
EXECUTABLE_EXTENSION = dylib;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||
GCC_ENABLE_CPP_RTTI = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "";
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
|
||||
GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
|
||||
GCC_WARN_MISSING_PARENTHESES = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = NO;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
|
||||
INSTALL_PATH = /usr/lib/system;
|
||||
INSTALL_PATH_PREFIX = "$(INSTALL_PATH_PREFIX_$(PLATFORM_NAME))";
|
||||
INSTALL_PATH_PREFIX_iphonesimulator = "$(SDKROOT)";
|
||||
IS_ZIPPERED = YES;
|
||||
LIBSYSTEM_LIBS = "$(LIBSYSTEM_LIBS_$(PLATFORM_NAME))";
|
||||
LIBSYSTEM_LIBS_iphoneos = "-lsystem_c -ldyld";
|
||||
LIBSYSTEM_LIBS_iphonesimulator = "-lsystem_sim_c -ldyld_sim -Wl,-upward-lSystem";
|
||||
LIBSYSTEM_LIBS_macosx = "-lsystem_malloc -lsystem_pthread -lsystem_platform -lsystem_c -ldyld -lkeymgr ";
|
||||
MACH_O_TYPE = mh_dylib;
|
||||
OTHER_CFLAGS = "-fexceptions";
|
||||
OTHER_CPLUSPLUSFLAGS = "-funwind-tables";
|
||||
OTHER_LDFLAGS = (
|
||||
"-L$(SDKROOT)/usr/lib/system",
|
||||
"-nodefaultlibs",
|
||||
"$(LIBSYSTEM_LIBS)",
|
||||
"-Wl,-umbrella,System",
|
||||
);
|
||||
PRODUCT_NAME = "$(PRODUCT_NAME_$(PLATFORM_NAME))";
|
||||
PRODUCT_NAME_iphoneos = libunwind;
|
||||
PRODUCT_NAME_iphonesimulator = libunwind_sim;
|
||||
PRODUCT_NAME_macosx = libunwind;
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F95A3D940DE3A8AA004B72E5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_CURRENT_VERSION = "$(RC_ProjectSourceVersion)";
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
|
||||
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||
GCC_ENABLE_CPP_RTTI = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = s;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
|
||||
HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
|
||||
INSTALL_PATH = "$(INSTALL_PATH_PREFIX)/usr/lib/system";
|
||||
INSTALL_PATH_PREFIX = "$(INSTALL_PATH_PREFIX_$(PLATFORM_NAME))";
|
||||
INSTALL_PATH_PREFIX_iphonesimulator = "$(SDKROOT)";
|
||||
IS_ZIPPERED = YES;
|
||||
LD_DYLIB_INSTALL_NAME = "/usr/lib/system/$(PRODUCT_NAME).dylib";
|
||||
LIBSYSTEM_LIBS = "$(LIBSYSTEM_LIBS_$(PLATFORM_NAME))";
|
||||
LIBSYSTEM_LIBS_iphoneos = "-lsystem_c -ldyld -Wl,-upward-lSystem";
|
||||
LIBSYSTEM_LIBS_iphonesimulator = "-lsystem_sim_c -ldyld_sim -Wl,-upward-lSystem";
|
||||
LIBSYSTEM_LIBS_macosx = "-lsystem_malloc -lsystem_pthread -lsystem_platform -lsystem_c -ldyld -lkeymgr ";
|
||||
MACH_O_TYPE = mh_dylib;
|
||||
ORDER_FILE = "$(SRCROOT)/libunwind.order";
|
||||
OTHER_CFLAGS = "-fexceptions";
|
||||
OTHER_CPLUSPLUSFLAGS = "-funwind-tables";
|
||||
OTHER_LDFLAGS = (
|
||||
"-L$(SDKROOT)/usr/lib/system",
|
||||
"-nodefaultlibs",
|
||||
"$(LIBSYSTEM_LIBS)",
|
||||
"-Wl,-umbrella,System",
|
||||
"-L/usr/lib/system",
|
||||
);
|
||||
PRODUCT_NAME = "$(PRODUCT_NAME_$(PLATFORM_NAME))";
|
||||
PRODUCT_NAME_iphoneos = libunwind;
|
||||
PRODUCT_NAME_iphonesimulator = libunwind_sim;
|
||||
PRODUCT_NAME_macosx = libunwind;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "libunwind" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB914F08733D8E0010E9CD /* Debug */,
|
||||
1DEB915008733D8E0010E9CD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F9276F110E6E0B6100B731C9 /* Build configuration list for PBXNativeTarget "dyld-libunwind.a" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F9276F120E6E0B6100B731C9 /* Debug */,
|
||||
F9276F130E6E0B6100B731C9 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F93A98F70EC91298000D227E /* Build configuration list for PBXAggregateTarget "all" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F93A98EE0EC91269000D227E /* Debug */,
|
||||
F93A98EF0EC91269000D227E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F95A3D920DE3A8AA004B72E5 /* Build configuration list for PBXNativeTarget "libunwind.dylib" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F95A3D930DE3A8AA004B72E5 /* Debug */,
|
||||
F95A3D940DE3A8AA004B72E5 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
}
|
7
libunwind.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
libunwind.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
BIN
libunwind.xcodeproj/project.xcworkspace/xcuserdata/kledzik.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
libunwind.xcodeproj/project.xcworkspace/xcuserdata/kledzik.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>all.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>dyld-libunwind.a.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>libunwind.dylib.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
431
src/AddressSpace.hpp
Normal file
431
src/AddressSpace.hpp
Normal file
@ -0,0 +1,431 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
//
|
||||
// C++ interface to lower levels of libuwind
|
||||
//
|
||||
|
||||
#ifndef __ADDRESSSPACE_HPP__
|
||||
#define __ADDRESSSPACE_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/getsect.h>
|
||||
#include <mach-o/dyld_priv.h>
|
||||
#include <Availability.h>
|
||||
|
||||
#include "FileAbstraction.hpp"
|
||||
#include "libunwind.h"
|
||||
#include "InternalMacros.h"
|
||||
#include "dwarf2.h"
|
||||
|
||||
|
||||
#if __i386__ && defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
|
||||
// For iOS simulator to link, we need a __dyld section
|
||||
// We need one to access private _dyld_func_lookup function.
|
||||
|
||||
struct __DATA__dyld { long lazy; int (*lookup)(const char*, void**); };
|
||||
|
||||
static volatile struct __DATA__dyld myDyldSection __attribute__ ((section ("__DATA,__dyld"))) = { 0, NULL };
|
||||
|
||||
|
||||
static int my_dyld_func_lookup(const char* dyld_func_name, void **address)
|
||||
{
|
||||
return (*myDyldSection.lookup)(dyld_func_name, address);
|
||||
}
|
||||
|
||||
bool _dyld_find_unwind_sections(void* addr, dyld_unwind_sections* info)
|
||||
{
|
||||
static void* (*p)(void*, dyld_unwind_sections*) = NULL;
|
||||
|
||||
if(p == NULL)
|
||||
my_dyld_func_lookup("__dyld_find_unwind_sections", (void**)&p);
|
||||
return p(addr, info);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace libunwind {
|
||||
|
||||
///
|
||||
/// LocalAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
|
||||
/// in the same process. It compiles away and making local unwinds very fast.
|
||||
///
|
||||
class LocalAddressSpace
|
||||
{
|
||||
public:
|
||||
|
||||
#if __LP64__
|
||||
typedef uint64_t pint_t;
|
||||
typedef int64_t sint_t;
|
||||
#else
|
||||
typedef uint32_t pint_t;
|
||||
typedef int32_t sint_t;
|
||||
#endif
|
||||
uint8_t get8(pint_t addr) { return *((uint8_t*)addr); }
|
||||
uint16_t get16(pint_t addr) { return *((uint16_t*)addr); }
|
||||
uint32_t get32(pint_t addr) { return *((uint32_t*)addr); }
|
||||
uint64_t get64(pint_t addr) { return *((uint64_t*)addr); }
|
||||
double getDouble(pint_t addr) { return *((double*)addr); }
|
||||
v128 getVector(pint_t addr) { return *((v128*)addr); }
|
||||
uintptr_t getP(pint_t addr);
|
||||
static uint64_t getULEB128(pint_t& addr, pint_t end);
|
||||
static int64_t getSLEB128(pint_t& addr, pint_t end);
|
||||
|
||||
pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
|
||||
bool findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
|
||||
bool findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart);
|
||||
|
||||
};
|
||||
|
||||
LocalAddressSpace sThisAddress;
|
||||
|
||||
inline uintptr_t LocalAddressSpace::getP(pint_t addr)
|
||||
{
|
||||
#if __LP64__
|
||||
return get64(addr);
|
||||
#else
|
||||
return get32(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Read a ULEB128 into a 64-bit word. */
|
||||
inline uint64_t
|
||||
LocalAddressSpace::getULEB128(pint_t& addr, pint_t end)
|
||||
{
|
||||
const uint8_t* p = (uint8_t*)addr;
|
||||
const uint8_t* pend = (uint8_t*)end;
|
||||
uint64_t result = 0;
|
||||
int bit = 0;
|
||||
do {
|
||||
uint64_t b;
|
||||
|
||||
if ( p == pend )
|
||||
ABORT("truncated uleb128 expression");
|
||||
|
||||
b = *p & 0x7f;
|
||||
|
||||
if (bit >= 64 || b << bit >> bit != b) {
|
||||
ABORT("malformed uleb128 expression");
|
||||
}
|
||||
else {
|
||||
result |= b << bit;
|
||||
bit += 7;
|
||||
}
|
||||
} while ( *p++ >= 0x80 );
|
||||
addr = (pint_t)p;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Read a SLEB128 into a 64-bit word. */
|
||||
inline int64_t
|
||||
LocalAddressSpace::getSLEB128(pint_t& addr, pint_t end)
|
||||
{
|
||||
const uint8_t* p = (uint8_t*)addr;
|
||||
int64_t result = 0;
|
||||
int bit = 0;
|
||||
uint8_t byte;
|
||||
do {
|
||||
byte = *p++;
|
||||
result |= ((byte & 0x7f) << bit);
|
||||
bit += 7;
|
||||
} while (byte & 0x80);
|
||||
// sign extend negative numbers
|
||||
if ( (byte & 0x40) != 0 )
|
||||
result |= (-1LL) << bit;
|
||||
addr = (pint_t)p;
|
||||
return result;
|
||||
}
|
||||
|
||||
LocalAddressSpace::pint_t
|
||||
LocalAddressSpace::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
|
||||
{
|
||||
pint_t startAddr = addr;
|
||||
const uint8_t* p = (uint8_t*)addr;
|
||||
pint_t result;
|
||||
|
||||
// first get value
|
||||
switch (encoding & 0x0F) {
|
||||
case DW_EH_PE_ptr:
|
||||
result = getP(addr);
|
||||
p += sizeof(pint_t);
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_uleb128:
|
||||
result = getULEB128(addr, end);
|
||||
break;
|
||||
case DW_EH_PE_udata2:
|
||||
result = get16(addr);
|
||||
p += 2;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_udata4:
|
||||
result = get32(addr);
|
||||
p += 4;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_udata8:
|
||||
result = get64(addr);
|
||||
p += 8;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_sleb128:
|
||||
result = getSLEB128(addr, end);
|
||||
break;
|
||||
case DW_EH_PE_sdata2:
|
||||
result = (int16_t)get16(addr);
|
||||
p += 2;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_sdata4:
|
||||
result = (int32_t)get32(addr);
|
||||
p += 4;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
case DW_EH_PE_sdata8:
|
||||
result = get64(addr);
|
||||
p += 8;
|
||||
addr = (pint_t)p;
|
||||
break;
|
||||
default:
|
||||
ABORT("unknown pointer encoding");
|
||||
}
|
||||
|
||||
// then add relative offset
|
||||
switch ( encoding & 0x70 ) {
|
||||
case DW_EH_PE_absptr:
|
||||
// do nothing
|
||||
break;
|
||||
case DW_EH_PE_pcrel:
|
||||
result += startAddr;
|
||||
break;
|
||||
case DW_EH_PE_textrel:
|
||||
ABORT("DW_EH_PE_textrel pointer encoding not supported");
|
||||
break;
|
||||
case DW_EH_PE_datarel:
|
||||
ABORT("DW_EH_PE_datarel pointer encoding not supported");
|
||||
break;
|
||||
case DW_EH_PE_funcrel:
|
||||
ABORT("DW_EH_PE_funcrel pointer encoding not supported");
|
||||
break;
|
||||
case DW_EH_PE_aligned:
|
||||
ABORT("DW_EH_PE_aligned pointer encoding not supported");
|
||||
break;
|
||||
default:
|
||||
ABORT("unknown pointer encoding");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( encoding & DW_EH_PE_indirect )
|
||||
result = getP(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
inline bool LocalAddressSpace::findUnwindSections(pint_t addr, pint_t& mh, pint_t& dwarfStart, pint_t& dwarfLen, pint_t& compactStart)
|
||||
{
|
||||
dyld_unwind_sections info;
|
||||
if ( _dyld_find_unwind_sections((void*)addr, &info) ) {
|
||||
mh = (pint_t)info.mh;
|
||||
dwarfStart = (pint_t)info.dwarf_section;
|
||||
dwarfLen = (pint_t)info.dwarf_section_length;
|
||||
compactStart = (pint_t)info.compact_unwind_section;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
|
||||
{
|
||||
dl_info dyldInfo;
|
||||
if ( dladdr((void*)addr, &dyldInfo) ) {
|
||||
if ( dyldInfo.dli_sname != NULL ) {
|
||||
strlcpy(buf, dyldInfo.dli_sname, bufLen);
|
||||
*offset = (addr - (pint_t)dyldInfo.dli_saddr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if UNW_REMOTE
|
||||
|
||||
///
|
||||
/// OtherAddressSpace is used as a template parameter to UnwindCursor when unwinding a thread
|
||||
/// in the another process. The other process can be a different endianness and a different
|
||||
/// pointer size and is handled by the P template parameter.
|
||||
///
|
||||
template <typename P>
|
||||
class OtherAddressSpace
|
||||
{
|
||||
public:
|
||||
OtherAddressSpace(task_t task) : fTask(task) {}
|
||||
|
||||
typedef typename P::uint_t pint_t;
|
||||
|
||||
uint8_t get8(pint_t addr);
|
||||
uint16_t get16(pint_t addr);
|
||||
uint32_t get32(pint_t addr);
|
||||
uint64_t get64(pint_t addr);
|
||||
pint_t getP(pint_t addr);
|
||||
uint64_t getULEB128(pint_t& addr, pint_t end);
|
||||
int64_t getSLEB128(pint_t& addr, pint_t end);
|
||||
pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
|
||||
bool findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset);
|
||||
bool findUnwindSections(pint_t addr, unwind_sections& info);
|
||||
private:
|
||||
void* localCopy(pint_t addr);
|
||||
|
||||
|
||||
task_t fTask;
|
||||
};
|
||||
|
||||
|
||||
template <typename P>
|
||||
uint8_t OtherAddressSpace<P>::get8(pint_t addr)
|
||||
{
|
||||
return *((uint8_t*)localCopy(addr));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
uint16_t OtherAddressSpace<P>::get16(pint_t addr)
|
||||
{
|
||||
return P::E::get16(*(uint16_t*)localCopy(addr));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
uint32_t OtherAddressSpace<P>::get32(pint_t addr)
|
||||
{
|
||||
return P::E::get32(*(uint32_t*)localCopy(addr));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
uint64_t OtherAddressSpace<P>::get64(pint_t addr)
|
||||
{
|
||||
return P::E::get64(*(uint64_t*)localCopy(addr));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr)
|
||||
{
|
||||
return P::getP(*(uint64_t*)localCopy(addr));
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
uint64_t OtherAddressSpace<P>::getULEB128(pint_t& addr, pint_t end)
|
||||
{
|
||||
uintptr_t size = (end - addr);
|
||||
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t)localCopy(addr);
|
||||
LocalAddressSpace::pint_t sladdr = laddr;
|
||||
uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr+size);
|
||||
addr += (laddr-sladdr);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
int64_t OtherAddressSpace<P>::getSLEB128(pint_t& addr, pint_t end)
|
||||
{
|
||||
uintptr_t size = (end - addr);
|
||||
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t)localCopy(addr);
|
||||
LocalAddressSpace::pint_t sladdr = laddr;
|
||||
uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr+size);
|
||||
addr += (laddr-sladdr);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void* OtherAddressSpace<P>::localCopy(pint_t addr)
|
||||
{
|
||||
// FIX ME
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
bool OtherAddressSpace<P>::findFunctionName(pint_t addr, char* buf, size_t bufLen, unw_word_t* offset)
|
||||
{
|
||||
// FIX ME
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// unw_addr_space is the base class that abstract unw_addr_space_t type in libunwind.h points to.
|
||||
///
|
||||
struct unw_addr_space
|
||||
{
|
||||
cpu_type_t cpuType;
|
||||
task_t taskPort;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points to when examining
|
||||
/// a 32-bit intel process.
|
||||
///
|
||||
struct unw_addr_space_i386 : public unw_addr_space
|
||||
{
|
||||
unw_addr_space_i386(task_t task) : oas(task) {}
|
||||
OtherAddressSpace<Pointer32<LittleEndian> > oas;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t points to when examining
|
||||
/// a 64-bit intel process.
|
||||
///
|
||||
struct unw_addr_space_x86_64 : public unw_addr_space
|
||||
{
|
||||
unw_addr_space_x86_64(task_t task) : oas(task) {}
|
||||
OtherAddressSpace<Pointer64<LittleEndian> > oas;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points to when examining
|
||||
/// a 32-bit PowerPC process.
|
||||
///
|
||||
struct unw_addr_space_ppc : public unw_addr_space
|
||||
{
|
||||
unw_addr_space_ppc(task_t task) : oas(task) {}
|
||||
OtherAddressSpace<Pointer32<BigEndian> > oas;
|
||||
};
|
||||
|
||||
|
||||
#endif // UNW_REMOTE
|
||||
|
||||
|
||||
} // namespace libunwind
|
||||
|
||||
|
||||
#endif // __ADDRESSSPACE_HPP__
|
||||
|
||||
|
||||
|
||||
|
1028
src/CompactUnwinder.hpp
Normal file
1028
src/CompactUnwinder.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1740
src/DwarfInstructions.hpp
Normal file
1740
src/DwarfInstructions.hpp
Normal file
File diff suppressed because it is too large
Load Diff
819
src/DwarfParser.hpp
Normal file
819
src/DwarfParser.hpp
Normal file
@ -0,0 +1,819 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2008-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
//
|
||||
// processor specific parsing of dwarf unwind instructions
|
||||
//
|
||||
|
||||
#ifndef __DWARF_PARSER_HPP__
|
||||
#define __DWARF_PARSER_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "libunwind.h"
|
||||
#include "dwarf2.h"
|
||||
|
||||
#include "AddressSpace.hpp"
|
||||
|
||||
|
||||
namespace libunwind {
|
||||
|
||||
|
||||
///
|
||||
/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
|
||||
/// See Dwarf Spec for details:
|
||||
/// http://www.linux-foundation.org/spec/booksets/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
|
||||
///
|
||||
template <typename A>
|
||||
class CFI_Parser
|
||||
{
|
||||
public:
|
||||
typedef typename A::pint_t pint_t;
|
||||
|
||||
///
|
||||
/// Information encoded in a CIE (Common Information Entry)
|
||||
///
|
||||
struct CIE_Info {
|
||||
pint_t cieStart;
|
||||
pint_t cieLength;
|
||||
pint_t cieInstructions;
|
||||
uint8_t pointerEncoding;
|
||||
uint8_t lsdaEncoding;
|
||||
uint8_t personalityEncoding;
|
||||
uint8_t personalityOffsetInCIE;
|
||||
pint_t personality;
|
||||
int codeAlignFactor;
|
||||
int dataAlignFactor;
|
||||
bool isSignalFrame;
|
||||
bool fdesHaveAugmentationData;
|
||||
};
|
||||
|
||||
///
|
||||
/// Information about an FDE (Frame Description Entry)
|
||||
///
|
||||
struct FDE_Info {
|
||||
pint_t fdeStart;
|
||||
pint_t fdeLength;
|
||||
pint_t fdeInstructions;
|
||||
pint_t pcStart;
|
||||
pint_t pcEnd;
|
||||
pint_t lsda;
|
||||
};
|
||||
|
||||
///
|
||||
/// Used by linker when parsing __eh_frame section
|
||||
///
|
||||
struct FDE_Reference {
|
||||
pint_t address;
|
||||
uint32_t offsetInFDE;
|
||||
uint8_t encodingOfAddress;
|
||||
};
|
||||
struct FDE_Atom_Info {
|
||||
pint_t fdeAddress;
|
||||
FDE_Reference function;
|
||||
FDE_Reference cie;
|
||||
FDE_Reference lsda;
|
||||
};
|
||||
struct CIE_Atom_Info {
|
||||
pint_t cieAddress;
|
||||
FDE_Reference personality;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// Information about a frame layout and registers saved determined
|
||||
/// by "running" the dwarf FDE "instructions"
|
||||
///
|
||||
enum { kMaxRegisterNumber = 120 };
|
||||
enum RegisterSavedWhere { kRegisterUnused, kRegisterInCFA, kRegisterOffsetFromCFA,
|
||||
kRegisterInRegister, kRegisterAtExpression, kRegisterIsExpression } ;
|
||||
struct RegisterLocation {
|
||||
RegisterSavedWhere location;
|
||||
int64_t value;
|
||||
};
|
||||
struct PrologInfo {
|
||||
uint32_t cfaRegister;
|
||||
int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
|
||||
int64_t cfaExpression; // CFA = expression
|
||||
uint32_t spExtraArgSize;
|
||||
uint32_t codeOffsetAtStackDecrement;
|
||||
uint8_t registerSavedTwiceInCIE;
|
||||
bool registersInOtherRegisters;
|
||||
bool registerSavedMoreThanOnce;
|
||||
bool cfaOffsetWasNegative;
|
||||
bool sameValueUsed;
|
||||
RegisterLocation savedRegisters[kMaxRegisterNumber]; // from where to restore registers
|
||||
};
|
||||
|
||||
struct PrologInfoStackEntry {
|
||||
PrologInfoStackEntry(PrologInfoStackEntry* n, const PrologInfo& i)
|
||||
: next(n), info(i) {}
|
||||
PrologInfoStackEntry* next;
|
||||
PrologInfo info;
|
||||
};
|
||||
|
||||
static bool findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo);
|
||||
static const char* decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo);
|
||||
static bool parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results);
|
||||
static const char* getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength,
|
||||
std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies);
|
||||
static uint32_t getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength);
|
||||
|
||||
static const char* parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo);
|
||||
|
||||
private:
|
||||
static bool parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo,
|
||||
pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results);
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// Parse a FDE into a CIE_Info and an FDE_Info
|
||||
///
|
||||
template <typename A>
|
||||
const char* CFI_Parser<A>::decodeFDE(A& addressSpace, pint_t fdeStart, FDE_Info* fdeInfo, CIE_Info* cieInfo)
|
||||
{
|
||||
pint_t p = fdeStart;
|
||||
uint64_t cfiLength = addressSpace.get32(p);
|
||||
p += 4;
|
||||
if ( cfiLength == 0xffffffff ) {
|
||||
// 0xffffffff means length is really next 8 bytes
|
||||
cfiLength = addressSpace.get64(p);
|
||||
p += 8;
|
||||
}
|
||||
if ( cfiLength == 0 )
|
||||
return "FDE has zero length"; // end marker
|
||||
uint32_t ciePointer = addressSpace.get32(p);
|
||||
if ( ciePointer == 0 )
|
||||
return "FDE is really a CIE"; // this is a CIE not an FDE
|
||||
pint_t nextCFI = p + cfiLength;
|
||||
pint_t cieStart = p-ciePointer;
|
||||
const char* err = parseCIE(addressSpace, cieStart, cieInfo);
|
||||
if (err != NULL)
|
||||
return err;
|
||||
p += 4;
|
||||
// parse pc begin and range
|
||||
pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
|
||||
pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
|
||||
// parse rest of info
|
||||
fdeInfo->lsda = 0;
|
||||
// check for augmentation length
|
||||
if ( cieInfo->fdesHaveAugmentationData ) {
|
||||
uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
|
||||
pint_t endOfAug = p + augLen;
|
||||
if ( cieInfo->lsdaEncoding != 0 ) {
|
||||
// peek at value (without indirection). Zero means no lsda
|
||||
pint_t lsdaStart = p;
|
||||
if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
|
||||
// reset pointer and re-parse lsda address
|
||||
p = lsdaStart;
|
||||
fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
|
||||
}
|
||||
}
|
||||
p = endOfAug;
|
||||
}
|
||||
fdeInfo->fdeStart = fdeStart;
|
||||
fdeInfo->fdeLength = nextCFI - fdeStart;
|
||||
fdeInfo->fdeInstructions = p;
|
||||
fdeInfo->pcStart = pcStart;
|
||||
fdeInfo->pcEnd = pcStart+pcRange;
|
||||
return NULL; // success
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Scan an eh_frame section to find an FDE for a pc
|
||||
///
|
||||
template <typename A>
|
||||
bool CFI_Parser<A>::findFDE(A& addressSpace, pint_t pc, pint_t ehSectionStart, uint32_t sectionLength, pint_t fdeHint, FDE_Info* fdeInfo, CIE_Info* cieInfo)
|
||||
{
|
||||
//fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
|
||||
pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
|
||||
const pint_t ehSectionEnd = p + sectionLength;
|
||||
while ( p < ehSectionEnd ) {
|
||||
pint_t currentCFI = p;
|
||||
//fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
|
||||
uint64_t cfiLength = addressSpace.get32(p);
|
||||
p += 4;
|
||||
if ( cfiLength == 0xffffffff ) {
|
||||
// 0xffffffff means length is really next 8 bytes
|
||||
cfiLength = addressSpace.get64(p);
|
||||
p += 8;
|
||||
}
|
||||
if ( cfiLength == 0 )
|
||||
return false; // end marker
|
||||
uint32_t id = addressSpace.get32(p);
|
||||
if ( id == 0 ) {
|
||||
// skip over CIEs
|
||||
p += cfiLength;
|
||||
}
|
||||
else {
|
||||
// process FDE to see if it covers pc
|
||||
pint_t nextCFI = p + cfiLength;
|
||||
uint32_t ciePointer = addressSpace.get32(p);
|
||||
pint_t cieStart = p-ciePointer;
|
||||
// validate pointer to CIE is within section
|
||||
if ( (ehSectionStart <= cieStart) && (cieStart < ehSectionEnd) ) {
|
||||
if ( parseCIE(addressSpace, cieStart, cieInfo) == NULL ) {
|
||||
p += 4;
|
||||
// parse pc begin and range
|
||||
pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
|
||||
pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
|
||||
//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
|
||||
// test if pc is within the function this FDE covers
|
||||
if ( (pcStart < pc) && (pc <= pcStart+pcRange) ) {
|
||||
// parse rest of info
|
||||
fdeInfo->lsda = 0;
|
||||
// check for augmentation length
|
||||
if ( cieInfo->fdesHaveAugmentationData ) {
|
||||
uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
|
||||
pint_t endOfAug = p + augLen;
|
||||
if ( cieInfo->lsdaEncoding != 0 ) {
|
||||
// peek at value (without indirection). Zero means no lsda
|
||||
pint_t lsdaStart = p;
|
||||
if ( addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0 ) {
|
||||
// reset pointer and re-parse lsda address
|
||||
p = lsdaStart;
|
||||
fdeInfo->lsda = addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
|
||||
}
|
||||
}
|
||||
p = endOfAug;
|
||||
}
|
||||
fdeInfo->fdeStart = currentCFI;
|
||||
fdeInfo->fdeLength = nextCFI - currentCFI;
|
||||
fdeInfo->fdeInstructions = p;
|
||||
fdeInfo->pcStart = pcStart;
|
||||
fdeInfo->pcEnd = pcStart+pcRange;
|
||||
//fprintf(stderr, "findFDE(pc=0x%llX) found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
//fprintf(stderr, "findFDE(pc=0x%llX) not found with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pc, (uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
|
||||
// pc is not in begin/range, skip this FDE
|
||||
}
|
||||
}
|
||||
else {
|
||||
// malformed CIE, now augmentation describing pc range encoding
|
||||
//fprintf(stderr, "malformed CIE\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
// malformed FDE. CIE is bad
|
||||
//fprintf(stderr, "malformed FDE, cieStart=0x%llX, ehSectionStart=0x%llX, ehSectionEnd=0x%llX\n",
|
||||
// (uint64_t)cieStart, (uint64_t)ehSectionStart, (uint64_t)ehSectionEnd);
|
||||
}
|
||||
p = nextCFI;
|
||||
}
|
||||
}
|
||||
//fprintf(stderr, "findFDE(pc=0x%llX) not found\n",(uint64_t)pc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Extract info from a CIE
|
||||
///
|
||||
template <typename A>
|
||||
const char* CFI_Parser<A>::parseCIE(A& addressSpace, pint_t cie, CIE_Info* cieInfo)
|
||||
{
|
||||
//fprintf(stderr, "parseCIE(0x%llX)\n", (long long)cie);
|
||||
cieInfo->pointerEncoding = 0;
|
||||
cieInfo->lsdaEncoding = 0;
|
||||
cieInfo->personalityEncoding = 0;
|
||||
cieInfo->personalityOffsetInCIE = 0;
|
||||
cieInfo->personality = 0;
|
||||
cieInfo->codeAlignFactor = 0;
|
||||
cieInfo->dataAlignFactor = 0;
|
||||
cieInfo->isSignalFrame = false;
|
||||
cieInfo->fdesHaveAugmentationData = false;
|
||||
cieInfo->cieStart = cie;
|
||||
pint_t p = cie;
|
||||
uint64_t cieLength = addressSpace.get32(p);
|
||||
p += 4;
|
||||
pint_t cieContentEnd = p + cieLength;
|
||||
if ( cieLength == 0xffffffff ) {
|
||||
// 0xffffffff means length is really next 8 bytes
|
||||
cieLength = addressSpace.get64(p);
|
||||
p += 8;
|
||||
cieContentEnd = p + cieLength;
|
||||
}
|
||||
if ( cieLength == 0 )
|
||||
return NULL;
|
||||
// CIE ID is always 0
|
||||
if ( addressSpace.get32(p) != 0 )
|
||||
return "CIE ID is not zero";
|
||||
p += 4;
|
||||
// Version is always 1 or 3
|
||||
uint8_t version = addressSpace.get8(p);
|
||||
if ( (version != 1) && (version != 3) )
|
||||
return "CIE version is not 1 or 3";
|
||||
++p;
|
||||
// save start of augmentation string and find end
|
||||
pint_t strStart = p;
|
||||
while ( addressSpace.get8(p) != 0 )
|
||||
++p;
|
||||
++p;
|
||||
// parse code aligment factor
|
||||
cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
|
||||
// parse data alignment factor
|
||||
cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
|
||||
// parse return address register
|
||||
addressSpace.getULEB128(p, cieContentEnd);
|
||||
// parse augmentation data based on augmentation string
|
||||
const char* result = NULL;
|
||||
if ( addressSpace.get8(strStart) == 'z' ) {
|
||||
// parse augmentation data length
|
||||
addressSpace.getULEB128(p, cieContentEnd);
|
||||
for (pint_t s=strStart; addressSpace.get8(s) != '\0'; ++s) {
|
||||
switch ( addressSpace.get8(s) ) {
|
||||
case 'z':
|
||||
cieInfo->fdesHaveAugmentationData = true;
|
||||
break;
|
||||
case 'P':
|
||||
cieInfo->personalityEncoding = addressSpace.get8(p);
|
||||
++p;
|
||||
cieInfo->personalityOffsetInCIE = p-cie;
|
||||
cieInfo->personality = addressSpace.getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
|
||||
break;
|
||||
case 'L':
|
||||
cieInfo->lsdaEncoding = addressSpace.get8(p);
|
||||
++p;
|
||||
break;
|
||||
case 'R':
|
||||
cieInfo->pointerEncoding = addressSpace.get8(p);
|
||||
++p;
|
||||
break;
|
||||
case 'S':
|
||||
cieInfo->isSignalFrame = true;
|
||||
break;
|
||||
default:
|
||||
// ignore unknown letters
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
|
||||
cieInfo->cieInstructions = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename A>
|
||||
uint32_t CFI_Parser<A>::getCFICount(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
const pint_t ehSectionEnd = ehSectionStart + sectionLength;
|
||||
for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
|
||||
uint64_t cfiLength = addressSpace.get32(p);
|
||||
p += 4;
|
||||
if ( cfiLength == 0xffffffff ) {
|
||||
// 0xffffffff means length is really next 8 bytes
|
||||
cfiLength = addressSpace.get64(p);
|
||||
p += 8;
|
||||
}
|
||||
if ( cfiLength == 0 )
|
||||
return count; // end marker
|
||||
++count;
|
||||
p += cfiLength;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename A>
|
||||
const char* CFI_Parser<A>::getCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength,
|
||||
std::vector<FDE_Atom_Info>& fdes, std::vector<CIE_Atom_Info>& cies)
|
||||
{
|
||||
const pint_t ehSectionEnd = ehSectionStart + sectionLength;
|
||||
for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
|
||||
pint_t currentCFI = p;
|
||||
uint64_t cfiLength = addressSpace.get32(p);
|
||||
p += 4;
|
||||
if ( cfiLength == 0xffffffff ) {
|
||||
// 0xffffffff means length is really next 8 bytes
|
||||
cfiLength = addressSpace.get64(p);
|
||||
p += 8;
|
||||
}
|
||||
if ( cfiLength == 0 )
|
||||
return NULL; // end marker
|
||||
uint32_t id = addressSpace.get32(p);
|
||||
if ( id == 0 ) {
|
||||
// is CIE
|
||||
CIE_Info cieInfo;
|
||||
const char* err = parseCIE(addressSpace, currentCFI, &cieInfo);
|
||||
if ( err != NULL )
|
||||
return err;
|
||||
CIE_Atom_Info entry;
|
||||
entry.cieAddress = currentCFI;
|
||||
entry.personality.address = cieInfo.personality;
|
||||
entry.personality.offsetInFDE = cieInfo.personalityOffsetInCIE;
|
||||
entry.personality.encodingOfAddress = cieInfo.personalityEncoding;
|
||||
cies.push_back(entry);
|
||||
p += cfiLength;
|
||||
}
|
||||
else {
|
||||
// is FDE
|
||||
FDE_Atom_Info entry;
|
||||
entry.fdeAddress = currentCFI;
|
||||
entry.function.address = 0;
|
||||
entry.cie.address = 0;
|
||||
entry.lsda.address = 0;
|
||||
pint_t nextCFI = p + cfiLength;
|
||||
uint32_t ciePointer = addressSpace.get32(p);
|
||||
pint_t cieStart = p-ciePointer;
|
||||
// validate pointer to CIE is within section
|
||||
if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
|
||||
return "FDE points to CIE outside __eh_frame section";
|
||||
CIE_Info cieInfo;
|
||||
const char* err = parseCIE(addressSpace, cieStart, &cieInfo);
|
||||
if ( err != NULL )
|
||||
return err;
|
||||
entry.cie.address = cieStart;
|
||||
entry.cie.offsetInFDE = p-currentCFI;
|
||||
entry.cie.encodingOfAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
|
||||
p += 4;
|
||||
// parse pc begin and range
|
||||
pint_t offsetOfFunctionAddress = p-currentCFI;
|
||||
pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
|
||||
pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
|
||||
//fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
|
||||
// test if pc is within the function this FDE covers
|
||||
entry.function.address = pcStart;
|
||||
entry.function.offsetInFDE = offsetOfFunctionAddress;
|
||||
entry.function.encodingOfAddress = cieInfo.pointerEncoding;
|
||||
// skip over augmentation length
|
||||
if ( cieInfo.fdesHaveAugmentationData ) {
|
||||
uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
|
||||
pint_t endOfAug = p + augLen;
|
||||
if ( (cieInfo.lsdaEncoding != 0) && (addressSpace.getP(p) != 0) ) {
|
||||
pint_t offsetOfLSDAAddress = p-currentCFI;
|
||||
entry.lsda.address = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
|
||||
entry.lsda.offsetInFDE = offsetOfLSDAAddress;
|
||||
entry.lsda.encodingOfAddress = cieInfo.lsdaEncoding;
|
||||
}
|
||||
p = endOfAug;
|
||||
}
|
||||
fdes.push_back(entry);
|
||||
p = nextCFI;
|
||||
}
|
||||
}
|
||||
return NULL; // success
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
|
||||
///
|
||||
template <typename A>
|
||||
bool CFI_Parser<A>::parseFDEInstructions(A& addressSpace, const FDE_Info& fdeInfo, const CIE_Info& cieInfo, pint_t upToPC, PrologInfo* results)
|
||||
{
|
||||
// clear results
|
||||
bzero(results, sizeof(PrologInfo));
|
||||
PrologInfoStackEntry* rememberStack = NULL;
|
||||
|
||||
// parse CIE then FDE instructions
|
||||
return parseInstructions(addressSpace, cieInfo.cieInstructions, cieInfo.cieStart+cieInfo.cieLength,
|
||||
cieInfo, (pint_t)(-1), rememberStack, results)
|
||||
&& parseInstructions(addressSpace, fdeInfo.fdeInstructions, fdeInfo.fdeStart+fdeInfo.fdeLength,
|
||||
cieInfo, upToPC-fdeInfo.pcStart, rememberStack, results);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// "run" the dwarf instructions
|
||||
///
|
||||
template <typename A>
|
||||
bool CFI_Parser<A>::parseInstructions(A& addressSpace, pint_t instructions, pint_t instructionsEnd, const CIE_Info& cieInfo,
|
||||
pint_t pcoffset, PrologInfoStackEntry*& rememberStack, PrologInfo* results)
|
||||
{
|
||||
const bool logDwarf = false;
|
||||
pint_t p = instructions;
|
||||
uint32_t codeOffset = 0;
|
||||
PrologInfo initialState = *results;
|
||||
if ( logDwarf ) fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n", (uint64_t)instructionsEnd);
|
||||
|
||||
// see Dwarf Spec, section 6.4.2 for details on unwind opcodes
|
||||
while ( (p < instructionsEnd) && (codeOffset < pcoffset) ) {
|
||||
uint64_t reg;
|
||||
uint64_t reg2;
|
||||
int64_t offset;
|
||||
uint64_t length;
|
||||
uint8_t opcode = addressSpace.get8(p);
|
||||
uint8_t operand;
|
||||
PrologInfoStackEntry* entry;
|
||||
++p;
|
||||
switch (opcode) {
|
||||
case DW_CFA_nop:
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_nop\n");
|
||||
break;
|
||||
case DW_CFA_set_loc:
|
||||
codeOffset = addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_set_loc\n");
|
||||
break;
|
||||
case DW_CFA_advance_loc1:
|
||||
codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
|
||||
p += 1;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc1: new offset=%u\n", codeOffset);
|
||||
break;
|
||||
case DW_CFA_advance_loc2:
|
||||
codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
|
||||
p += 2;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc2: new offset=%u\n", codeOffset);
|
||||
break;
|
||||
case DW_CFA_advance_loc4:
|
||||
codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
|
||||
p += 4;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc4: new offset=%u\n", codeOffset);
|
||||
break;
|
||||
case DW_CFA_offset_extended:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
if ( results->savedRegisters[reg].location != kRegisterUnused )
|
||||
results->registerSavedMoreThanOnce = true;
|
||||
results->savedRegisters[reg].location = kRegisterInCFA;
|
||||
results->savedRegisters[reg].value = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_restore_extended:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);;
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->savedRegisters[reg] = initialState.savedRegisters[reg];
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
|
||||
break;
|
||||
case DW_CFA_undefined:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->savedRegisters[reg].location = kRegisterUnused;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
|
||||
break;
|
||||
case DW_CFA_same_value:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
// <rdar://problem/8456377> DW_CFA_same_value unsupported
|
||||
// "same value" means register was stored in frame, but its current
|
||||
// value has not changed, so no need to restore from frame.
|
||||
// We model this as if the register was never saved.
|
||||
results->savedRegisters[reg].location = kRegisterUnused;
|
||||
// set flag to disable conversion to compact unwind
|
||||
results->sameValueUsed = true;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
|
||||
break;
|
||||
case DW_CFA_register:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
reg2 = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
if ( reg2 > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
|
||||
return false;
|
||||
}
|
||||
results->savedRegisters[reg].location = kRegisterInRegister;
|
||||
results->savedRegisters[reg].value = reg2;
|
||||
// set flag to disable conversion to compact unwind
|
||||
results->registersInOtherRegisters = true;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
|
||||
break;
|
||||
case DW_CFA_remember_state:
|
||||
// avoid operator new, because that would be an upward dependency
|
||||
entry = (PrologInfoStackEntry*)malloc(sizeof(PrologInfoStackEntry));
|
||||
if ( entry != NULL ) {
|
||||
entry->next = rememberStack;
|
||||
entry->info = *results;
|
||||
rememberStack = entry;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_remember_state\n");
|
||||
break;
|
||||
case DW_CFA_restore_state:
|
||||
if ( rememberStack != NULL ) {
|
||||
PrologInfoStackEntry* top = rememberStack;
|
||||
*results = top->info;
|
||||
rememberStack = top->next;
|
||||
free((char*)top);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_restore_state\n");
|
||||
break;
|
||||
case DW_CFA_def_cfa:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->cfaRegister = reg;
|
||||
results->cfaRegisterOffset = offset;
|
||||
if ( offset > 0x80000000 )
|
||||
results->cfaOffsetWasNegative = true;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_def_cfa_register:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->cfaRegister = reg;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
|
||||
break;
|
||||
case DW_CFA_def_cfa_offset:
|
||||
results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
|
||||
results->codeOffsetAtStackDecrement = codeOffset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n", results->cfaRegisterOffset);
|
||||
break;
|
||||
case DW_CFA_def_cfa_expression:
|
||||
results->cfaRegister = 0;
|
||||
results->cfaExpression = p;
|
||||
length = addressSpace.getULEB128(p, instructionsEnd);
|
||||
p += length;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n",
|
||||
results->cfaExpression, length);
|
||||
break;
|
||||
case DW_CFA_expression:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_expression dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->savedRegisters[reg].location = kRegisterAtExpression;
|
||||
results->savedRegisters[reg].value = p;
|
||||
length = addressSpace.getULEB128(p, instructionsEnd);
|
||||
p += length;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n",
|
||||
reg, results->savedRegisters[reg].value, length);
|
||||
break;
|
||||
case DW_CFA_offset_extended_sf:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
if ( results->savedRegisters[reg].location != kRegisterUnused )
|
||||
results->registerSavedMoreThanOnce = true;
|
||||
results->savedRegisters[reg].location = kRegisterInCFA;
|
||||
results->savedRegisters[reg].value = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_def_cfa_sf:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->cfaRegister = reg;
|
||||
results->cfaRegisterOffset = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_def_cfa_offset_sf:
|
||||
results->cfaRegisterOffset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
results->codeOffsetAtStackDecrement = codeOffset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n", results->cfaRegisterOffset);
|
||||
break;
|
||||
case DW_CFA_val_offset:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
|
||||
results->savedRegisters[reg].value = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_val_offset_sf:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
|
||||
results->savedRegisters[reg].value = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg, offset);
|
||||
break;
|
||||
case DW_CFA_val_expression:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
results->savedRegisters[reg].location = kRegisterIsExpression;
|
||||
results->savedRegisters[reg].value = p;
|
||||
length = addressSpace.getULEB128(p, instructionsEnd);
|
||||
p += length;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n",
|
||||
reg, results->savedRegisters[reg].value, length);
|
||||
break;
|
||||
case DW_CFA_GNU_args_size:
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd);
|
||||
results->spExtraArgSize = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", offset);
|
||||
break;
|
||||
case DW_CFA_GNU_negative_offset_extended:
|
||||
reg = addressSpace.getULEB128(p, instructionsEnd);
|
||||
if ( reg > kMaxRegisterNumber ) {
|
||||
fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf unwind, reg too big\n");
|
||||
return false;
|
||||
}
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
if ( results->savedRegisters[reg].location != kRegisterUnused )
|
||||
results->registerSavedMoreThanOnce = true;
|
||||
results->savedRegisters[reg].location = kRegisterInCFA;
|
||||
results->savedRegisters[reg].value = -offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
|
||||
break;
|
||||
default:
|
||||
operand = opcode & 0x3F;
|
||||
switch ( opcode & 0xC0 ) {
|
||||
case DW_CFA_offset:
|
||||
reg = operand;
|
||||
offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||
if ( results->savedRegisters[reg].location != kRegisterUnused ) {
|
||||
// look for idiom of PC saved twice in CIE to mean disable compact unwind encoding
|
||||
if ( (pcoffset == (pint_t)(-1))
|
||||
&& (results->savedRegisters[reg].location == kRegisterInCFA)
|
||||
&& (results->savedRegisters[reg].value == offset) )
|
||||
results->registerSavedTwiceInCIE = reg;
|
||||
else
|
||||
results->registerSavedMoreThanOnce = true;
|
||||
}
|
||||
results->savedRegisters[reg].location = kRegisterInCFA;
|
||||
results->savedRegisters[reg].value = offset;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand, offset);
|
||||
break;
|
||||
case DW_CFA_advance_loc:
|
||||
codeOffset += operand * cieInfo.codeAlignFactor;
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_advance_loc: new offset=%u\n", codeOffset);
|
||||
break;
|
||||
case DW_CFA_restore:
|
||||
// <rdar://problem/7503075> Python crashes when handling an exception thrown by an obj-c object
|
||||
// libffi uses DW_CFA_restore in the middle of some custom dwarf, so it is not a good epilog flag
|
||||
//return true; // gcc-4.5 starts the epilog with this
|
||||
reg = operand;
|
||||
results->savedRegisters[reg] = initialState.savedRegisters[reg];
|
||||
if ( logDwarf ) fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
|
||||
break;
|
||||
default:
|
||||
if ( logDwarf ) fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace libunwind
|
||||
|
||||
|
||||
#endif // __DWARF_PARSER_HPP__
|
||||
|
||||
|
||||
|
||||
|
146
src/FileAbstraction.hpp
Normal file
146
src/FileAbstraction.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2005-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
#ifndef __FILE_ABSTRACTION__
|
||||
#define __FILE_ABSTRACTION__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
#define INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
//
|
||||
// This abstraction layer is for use with file formats that have 64-bit/32-bit and Big-Endian/Little-Endian variants
|
||||
//
|
||||
// For example: to make a utility that handles 32-bit little enidan files use: Pointer32<LittleEndian>
|
||||
//
|
||||
//
|
||||
// get16() read a 16-bit number from an E endian struct
|
||||
// set16() write a 16-bit number to an E endian struct
|
||||
// get32() read a 32-bit number from an E endian struct
|
||||
// set32() write a 32-bit number to an E endian struct
|
||||
// get64() read a 64-bit number from an E endian struct
|
||||
// set64() write a 64-bit number to an E endian struct
|
||||
//
|
||||
// getBits() read a bit field from an E endian struct (bitCount=number of bits in field, firstBit=bit index of field)
|
||||
// setBits() write a bit field to an E endian struct (bitCount=number of bits in field, firstBit=bit index of field)
|
||||
//
|
||||
// getBitsRaw() read a bit field from a struct with native endianness
|
||||
// setBitsRaw() write a bit field from a struct with native endianness
|
||||
//
|
||||
|
||||
class BigEndian
|
||||
{
|
||||
public:
|
||||
static uint16_t get16(const uint16_t& from) INLINE { return OSReadBigInt16(&from, 0); }
|
||||
static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteBigInt16(&into, 0, value); }
|
||||
|
||||
static uint32_t get32(const uint32_t& from) INLINE { return OSReadBigInt32(&from, 0); }
|
||||
static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteBigInt32(&into, 0, value); }
|
||||
|
||||
static uint64_t get64(const uint64_t& from) INLINE { return OSReadBigInt64(&from, 0); }
|
||||
static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteBigInt64(&into, 0, value); }
|
||||
|
||||
static uint32_t getBits(const uint32_t& from,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); }
|
||||
static void setBits(uint32_t& into, uint32_t value,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); }
|
||||
|
||||
static uint32_t getBitsRaw(const uint32_t& from,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> (32-firstBit-bitCount)) & ((1<<bitCount)-1)); }
|
||||
static void setBitsRaw(uint32_t& into, uint32_t value,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into;
|
||||
const uint32_t mask = ((1<<bitCount)-1);
|
||||
temp &= ~(mask << (32-firstBit-bitCount));
|
||||
temp |= ((value & mask) << (32-firstBit-bitCount));
|
||||
into = temp; }
|
||||
enum { little_endian = 0 };
|
||||
};
|
||||
|
||||
|
||||
class LittleEndian
|
||||
{
|
||||
public:
|
||||
static uint16_t get16(const uint16_t& from) INLINE { return OSReadLittleInt16(&from, 0); }
|
||||
static void set16(uint16_t& into, uint16_t value) INLINE { OSWriteLittleInt16(&into, 0, value); }
|
||||
|
||||
static uint32_t get32(const uint32_t& from) INLINE { return OSReadLittleInt32(&from, 0); }
|
||||
static void set32(uint32_t& into, uint32_t value) INLINE { OSWriteLittleInt32(&into, 0, value); }
|
||||
|
||||
static uint64_t get64(const uint64_t& from) INLINE { return OSReadLittleInt64(&from, 0); }
|
||||
static void set64(uint64_t& into, uint64_t value) INLINE { OSWriteLittleInt64(&into, 0, value); }
|
||||
|
||||
static uint32_t getBits(const uint32_t& from,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { return getBitsRaw(get32(from), firstBit, bitCount); }
|
||||
static void setBits(uint32_t& into, uint32_t value,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = get32(into); setBitsRaw(temp, value, firstBit, bitCount); set32(into, temp); }
|
||||
|
||||
static uint32_t getBitsRaw(const uint32_t& from,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { return ((from >> firstBit) & ((1<<bitCount)-1)); }
|
||||
static void setBitsRaw(uint32_t& into, uint32_t value,
|
||||
uint8_t firstBit, uint8_t bitCount) INLINE { uint32_t temp = into;
|
||||
const uint32_t mask = ((1<<bitCount)-1);
|
||||
temp &= ~(mask << firstBit);
|
||||
temp |= ((value & mask) << firstBit);
|
||||
into = temp; }
|
||||
enum { little_endian = 1 };
|
||||
};
|
||||
|
||||
|
||||
template <typename _E>
|
||||
class Pointer32
|
||||
{
|
||||
public:
|
||||
typedef uint32_t uint_t;
|
||||
typedef _E E;
|
||||
|
||||
static uint64_t getP(const uint_t& from) INLINE { return _E::get32(from); }
|
||||
static void setP(uint_t& into, uint64_t value) INLINE { _E::set32(into, value); }
|
||||
};
|
||||
|
||||
|
||||
template <typename _E>
|
||||
class Pointer64
|
||||
{
|
||||
public:
|
||||
typedef uint64_t uint_t;
|
||||
typedef _E E;
|
||||
|
||||
static uint64_t getP(const uint_t& from) INLINE { return _E::get64(from); }
|
||||
static void setP(uint_t& into, uint64_t value) INLINE { _E::set64(into, value); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __FILE_ABSTRACTION__
|
||||
|
||||
|
104
src/InternalMacros.h
Normal file
104
src/InternalMacros.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef INTERNAL_MACROS_H
|
||||
#define INTERNAL_MACROS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <Availability.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void __assert_rtn(const char *, const char *, int, const char *) __attribute__((noreturn));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define UNW_STEP_SUCCESS 1
|
||||
#define UNW_STEP_END 0
|
||||
|
||||
|
||||
struct v128 { unsigned int vec[4]; };
|
||||
|
||||
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#define COMPILE_TIME_ASSERT( expr ) \
|
||||
extern int compile_time_assert_failed[ ( expr ) ? 1 : -1 ] __attribute__( ( unused ) );
|
||||
|
||||
#define ABORT(msg) __assert_rtn(__func__, __FILE__, __LINE__, msg)
|
||||
|
||||
#if NDEBUG
|
||||
#define DEBUG_MESSAGE(msg, ...)
|
||||
#define DEBUG_PRINT_API(msg, ...)
|
||||
#define DEBUG_PRINT_UNWINDING_TEST 0
|
||||
#define DEBUG_PRINT_UNWINDING(msg, ...)
|
||||
#define DEBUG_LOG_NON_ZERO(x) x;
|
||||
#define INITIALIZE_DEBUG_PRINT_API
|
||||
#define INITIALIZE_DEBUG_PRINT_UNWINDING
|
||||
#else
|
||||
#define DEBUG_MESSAGE(msg, ...) fprintf(stderr, "libuwind: " msg, __VA_ARGS__)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern bool logAPIs();
|
||||
extern bool logUnwinding();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#define DEBUG_LOG_NON_ZERO(x) { int _err = x; if ( _err != 0 ) fprintf(stderr, "libuwind: " #x "=%d in %s", _err, __FUNCTION__); }
|
||||
#define DEBUG_PRINT_API(msg, ...) do { if ( logAPIs() ) fprintf(stderr, msg, __VA_ARGS__); } while(0)
|
||||
#define DEBUG_PRINT_UNWINDING(msg, ...) do { if ( logUnwinding() ) fprintf(stderr, msg, __VA_ARGS__); } while(0)
|
||||
#define DEBUG_PRINT_UNWINDING_TEST logUnwinding()
|
||||
#define INITIALIZE_DEBUG_PRINT_API bool logAPIs() { static bool log = (getenv("LIBUNWIND_PRINT_APIS") != NULL); return log; }
|
||||
#define INITIALIZE_DEBUG_PRINT_UNWINDING bool logUnwinding() { static bool log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL); return log; }
|
||||
#endif
|
||||
|
||||
|
||||
// static linker symbols to prevent wrong two level namespace for _Unwind symbols
|
||||
#if __arm__
|
||||
#define NOT_HERE_BEFORE_5_0(sym) \
|
||||
extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
|
||||
extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
|
||||
extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
|
||||
extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
|
||||
extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
|
||||
extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
|
||||
extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp43 = 0;
|
||||
#endif
|
||||
|
||||
#define NOT_HERE_BEFORE_10_6(sym) \
|
||||
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
|
||||
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0;
|
||||
#define NEVER_HERE(sym) \
|
||||
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
|
||||
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
|
||||
extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
|
||||
|
||||
|
||||
|
||||
#endif // INTERNAL_MACROS_H
|
261
src/Registers.S
Normal file
261
src/Registers.S
Normal file
@ -0,0 +1,261 @@
|
||||
|
||||
|
||||
#if __i386__
|
||||
.text
|
||||
.globl __ZN9libunwind13Registers_x866jumptoEv
|
||||
.private_extern __ZN9libunwind13Registers_x866jumptoEv
|
||||
__ZN9libunwind13Registers_x866jumptoEv:
|
||||
#
|
||||
# void libunwind::Registers_x86::jumpto()
|
||||
#
|
||||
# On entry:
|
||||
# + +
|
||||
# +-----------------------+
|
||||
# + thread_state pointer +
|
||||
# +-----------------------+
|
||||
# + return address +
|
||||
# +-----------------------+ <-- SP
|
||||
# + +
|
||||
movl 4(%esp), %eax
|
||||
# set up eax and ret on new stack location
|
||||
movl 28(%eax), %edx # edx holds new stack pointer
|
||||
subl $8,%edx
|
||||
movl %edx, 28(%eax)
|
||||
movl 0(%eax), %ebx
|
||||
movl %ebx, 0(%edx)
|
||||
movl 40(%eax), %ebx
|
||||
movl %ebx, 4(%edx)
|
||||
# we now have ret and eax pushed onto where new stack will be
|
||||
# restore all registers
|
||||
movl 4(%eax), %ebx
|
||||
movl 8(%eax), %ecx
|
||||
movl 12(%eax), %edx
|
||||
movl 16(%eax), %edi
|
||||
movl 20(%eax), %esi
|
||||
movl 24(%eax), %ebp
|
||||
movl 28(%eax), %esp
|
||||
# skip ss
|
||||
# skip eflags
|
||||
pop %eax # eax was already pushed on new stack
|
||||
ret # eip was already pushed on new stack
|
||||
# skip cs
|
||||
# skip ds
|
||||
# skip es
|
||||
# skip fs
|
||||
# skip gs
|
||||
|
||||
#elif __x86_64__
|
||||
|
||||
.text
|
||||
.globl __ZN9libunwind16Registers_x86_646jumptoEv
|
||||
.private_extern __ZN9libunwind16Registers_x86_646jumptoEv
|
||||
__ZN9libunwind16Registers_x86_646jumptoEv:
|
||||
#
|
||||
# void libunwind::Registers_x86_64::jumpto()
|
||||
#
|
||||
# On entry, thread_state pointer is in rdi
|
||||
|
||||
movq 56(%rdi), %rax # rax holds new stack pointer
|
||||
subq $16, %rax
|
||||
movq %rax, 56(%rdi)
|
||||
movq 32(%rdi), %rbx # store new rdi on new stack
|
||||
movq %rbx, 0(%rax)
|
||||
movq 128(%rdi), %rbx # store new rip on new stack
|
||||
movq %rbx, 8(%rax)
|
||||
# restore all registers
|
||||
movq 0(%rdi), %rax
|
||||
movq 8(%rdi), %rbx
|
||||
movq 16(%rdi), %rcx
|
||||
movq 24(%rdi), %rdx
|
||||
# restore rdi later
|
||||
movq 40(%rdi), %rsi
|
||||
movq 48(%rdi), %rbp
|
||||
# restore rsp later
|
||||
movq 64(%rdi), %r8
|
||||
movq 72(%rdi), %r9
|
||||
movq 80(%rdi), %r10
|
||||
movq 88(%rdi), %r11
|
||||
movq 96(%rdi), %r12
|
||||
movq 104(%rdi), %r13
|
||||
movq 112(%rdi), %r14
|
||||
movq 120(%rdi), %r15
|
||||
# skip rflags
|
||||
# skip cs
|
||||
# skip fs
|
||||
# skip gs
|
||||
movq 56(%rdi), %rsp # cut back rsp to new location
|
||||
pop %rdi # rdi was saved here earlier
|
||||
ret # rip was saved here
|
||||
|
||||
|
||||
#elif __ppc__
|
||||
|
||||
.text
|
||||
.globl __ZN9libunwind13Registers_ppc6jumptoEv
|
||||
.private_extern __ZN9libunwind13Registers_ppc6jumptoEv
|
||||
__ZN9libunwind13Registers_ppc6jumptoEv:
|
||||
;
|
||||
; void libunwind::Registers_ppc::jumpto()
|
||||
;
|
||||
; On entry:
|
||||
; thread_state pointer is in r3
|
||||
;
|
||||
|
||||
; restore integral registerrs
|
||||
; skip r0 for now
|
||||
; skip r1 for now
|
||||
lwz r2, 16(r3)
|
||||
; skip r3 for now
|
||||
; skip r4 for now
|
||||
; skip r5 for now
|
||||
lwz r6, 32(r3)
|
||||
lwz r7, 36(r3)
|
||||
lwz r8, 40(r3)
|
||||
lwz r9, 44(r3)
|
||||
lwz r10, 48(r3)
|
||||
lwz r11, 52(r3)
|
||||
lwz r12, 56(r3)
|
||||
lwz r13, 60(r3)
|
||||
lwz r14, 64(r3)
|
||||
lwz r15, 68(r3)
|
||||
lwz r16, 72(r3)
|
||||
lwz r17, 76(r3)
|
||||
lwz r18, 80(r3)
|
||||
lwz r19, 84(r3)
|
||||
lwz r20, 88(r3)
|
||||
lwz r21, 92(r3)
|
||||
lwz r22, 96(r3)
|
||||
lwz r23,100(r3)
|
||||
lwz r24,104(r3)
|
||||
lwz r25,108(r3)
|
||||
lwz r26,112(r3)
|
||||
lwz r27,116(r3)
|
||||
lwz r28,120(r3)
|
||||
lwz r29,124(r3)
|
||||
lwz r30,128(r3)
|
||||
lwz r31,132(r3)
|
||||
|
||||
; restore float registers
|
||||
lfd f0, 160(r3)
|
||||
lfd f1, 168(r3)
|
||||
lfd f2, 176(r3)
|
||||
lfd f3, 184(r3)
|
||||
lfd f4, 192(r3)
|
||||
lfd f5, 200(r3)
|
||||
lfd f6, 208(r3)
|
||||
lfd f7, 216(r3)
|
||||
lfd f8, 224(r3)
|
||||
lfd f9, 232(r3)
|
||||
lfd f10,240(r3)
|
||||
lfd f11,248(r3)
|
||||
lfd f12,256(r3)
|
||||
lfd f13,264(r3)
|
||||
lfd f14,272(r3)
|
||||
lfd f15,280(r3)
|
||||
lfd f16,288(r3)
|
||||
lfd f17,296(r3)
|
||||
lfd f18,304(r3)
|
||||
lfd f19,312(r3)
|
||||
lfd f20,320(r3)
|
||||
lfd f21,328(r3)
|
||||
lfd f22,336(r3)
|
||||
lfd f23,344(r3)
|
||||
lfd f24,352(r3)
|
||||
lfd f25,360(r3)
|
||||
lfd f26,368(r3)
|
||||
lfd f27,376(r3)
|
||||
lfd f28,384(r3)
|
||||
lfd f29,392(r3)
|
||||
lfd f30,400(r3)
|
||||
lfd f31,408(r3)
|
||||
|
||||
; restore vector registers if any are in use
|
||||
lwz r5,156(r3) ; test VRsave
|
||||
cmpwi r5,0
|
||||
beq Lnovec
|
||||
|
||||
subi r4,r1,16
|
||||
rlwinm r4,r4,0,0,27 ; mask low 4-bits
|
||||
; r4 is now a 16-byte aligned pointer into the red zone
|
||||
; the fVectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
|
||||
|
||||
|
||||
#define LOAD_VECTOR_UNALIGNEDl(_index) \
|
||||
andis. r0,r5,(1<<(15-_index)) @\
|
||||
beq Ldone ## _index @\
|
||||
lwz r0, 424+_index*16(r3) @\
|
||||
stw r0, 0(r4) @\
|
||||
lwz r0, 424+_index*16+4(r3) @\
|
||||
stw r0, 4(r4) @\
|
||||
lwz r0, 424+_index*16+8(r3) @\
|
||||
stw r0, 8(r4) @\
|
||||
lwz r0, 424+_index*16+12(r3)@\
|
||||
stw r0, 12(r4) @\
|
||||
lvx v ## _index,0,r4 @\
|
||||
Ldone ## _index:
|
||||
|
||||
#define LOAD_VECTOR_UNALIGNEDh(_index) \
|
||||
andi. r0,r5,(1<<(31-_index)) @\
|
||||
beq Ldone ## _index @\
|
||||
lwz r0, 424+_index*16(r3) @\
|
||||
stw r0, 0(r4) @\
|
||||
lwz r0, 424+_index*16+4(r3) @\
|
||||
stw r0, 4(r4) @\
|
||||
lwz r0, 424+_index*16+8(r3) @\
|
||||
stw r0, 8(r4) @\
|
||||
lwz r0, 424+_index*16+12(r3)@\
|
||||
stw r0, 12(r4) @\
|
||||
lvx v ## _index,0,r4 @\
|
||||
Ldone ## _index:
|
||||
|
||||
|
||||
LOAD_VECTOR_UNALIGNEDl(0)
|
||||
LOAD_VECTOR_UNALIGNEDl(1)
|
||||
LOAD_VECTOR_UNALIGNEDl(2)
|
||||
LOAD_VECTOR_UNALIGNEDl(3)
|
||||
LOAD_VECTOR_UNALIGNEDl(4)
|
||||
LOAD_VECTOR_UNALIGNEDl(5)
|
||||
LOAD_VECTOR_UNALIGNEDl(6)
|
||||
LOAD_VECTOR_UNALIGNEDl(7)
|
||||
LOAD_VECTOR_UNALIGNEDl(8)
|
||||
LOAD_VECTOR_UNALIGNEDl(9)
|
||||
LOAD_VECTOR_UNALIGNEDl(10)
|
||||
LOAD_VECTOR_UNALIGNEDl(11)
|
||||
LOAD_VECTOR_UNALIGNEDl(12)
|
||||
LOAD_VECTOR_UNALIGNEDl(13)
|
||||
LOAD_VECTOR_UNALIGNEDl(14)
|
||||
LOAD_VECTOR_UNALIGNEDl(15)
|
||||
LOAD_VECTOR_UNALIGNEDh(16)
|
||||
LOAD_VECTOR_UNALIGNEDh(17)
|
||||
LOAD_VECTOR_UNALIGNEDh(18)
|
||||
LOAD_VECTOR_UNALIGNEDh(19)
|
||||
LOAD_VECTOR_UNALIGNEDh(20)
|
||||
LOAD_VECTOR_UNALIGNEDh(21)
|
||||
LOAD_VECTOR_UNALIGNEDh(22)
|
||||
LOAD_VECTOR_UNALIGNEDh(23)
|
||||
LOAD_VECTOR_UNALIGNEDh(24)
|
||||
LOAD_VECTOR_UNALIGNEDh(25)
|
||||
LOAD_VECTOR_UNALIGNEDh(26)
|
||||
LOAD_VECTOR_UNALIGNEDh(27)
|
||||
LOAD_VECTOR_UNALIGNEDh(28)
|
||||
LOAD_VECTOR_UNALIGNEDh(29)
|
||||
LOAD_VECTOR_UNALIGNEDh(30)
|
||||
LOAD_VECTOR_UNALIGNEDh(31)
|
||||
|
||||
Lnovec:
|
||||
lwz r0, 136(r3) ; __cr
|
||||
mtocrf 255,r0
|
||||
lwz r0, 148(r3) ; __ctr
|
||||
mtctr r0
|
||||
lwz r0, 0(r3) ; __ssr0
|
||||
mtctr r0
|
||||
lwz r0, 8(r3) ; do r0 now
|
||||
lwz r5,28(r3) ; do r5 now
|
||||
lwz r4,24(r3) ; do r4 now
|
||||
lwz r1,12(r3) ; do sp now
|
||||
lwz r3,20(r3) ; do r3 last
|
||||
bctr
|
||||
|
||||
|
||||
#endif
|
||||
|
1093
src/Registers.hpp
Normal file
1093
src/Registers.hpp
Normal file
File diff suppressed because it is too large
Load Diff
491
src/Unwind-sjlj.c
Normal file
491
src/Unwind-sjlj.c
Normal file
@ -0,0 +1,491 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*
|
||||
* Implements setjump-longjump based C++ exceptions
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <setjmp.h>
|
||||
#if !FOR_DYLD
|
||||
#include <System/pthread_machdep.h>
|
||||
#endif
|
||||
#include "unwind.h"
|
||||
#include "InternalMacros.h"
|
||||
|
||||
//
|
||||
// ARM uses setjump/longjump based C++ exceptions.
|
||||
// Other architectures use "zero cost" exceptions.
|
||||
//
|
||||
// With SJLJ based exceptions any function that has a catch clause or needs to do any clean up when
|
||||
// an exception propagates through it, needs to call _Unwind_SjLj_Register() at the start of the
|
||||
// function and _Unwind_SjLj_Unregister() at the end. The register function is called with the
|
||||
// address of a block of memory in the function's stack frame. The runtime keeps a linked list
|
||||
// (stack) of these blocks - one per thread. The calling function also sets the personality
|
||||
// and lsda fields of the block.
|
||||
//
|
||||
//
|
||||
#if __arm__
|
||||
|
||||
struct _Unwind_FunctionContext
|
||||
{
|
||||
// next function in stack of handlers
|
||||
struct _Unwind_FunctionContext* prev;
|
||||
|
||||
// set by calling function before registering to be the landing pad
|
||||
uintptr_t resumeLocation;
|
||||
|
||||
// set by personality handler to be parameters passed to landing pad function
|
||||
uintptr_t resumeParameters[4];
|
||||
|
||||
// set by calling function before registering
|
||||
__personality_routine personality; // arm offset=24
|
||||
uintptr_t lsda; // arm offset=28
|
||||
|
||||
// variable length array, contains registers to restore
|
||||
// 0 = r7, 1 = pc, 2 = sp
|
||||
void* jbuf[];
|
||||
};
|
||||
|
||||
|
||||
#if FOR_DYLD
|
||||
// implemented in dyld
|
||||
extern struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
extern void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc);
|
||||
#else
|
||||
static struct _Unwind_FunctionContext* __Unwind_SjLj_GetTopOfFunctionStack()
|
||||
{
|
||||
return (struct _Unwind_FunctionContext*)_pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
|
||||
}
|
||||
|
||||
static void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext* fc)
|
||||
{
|
||||
_pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Called at start of each function that catches exceptions
|
||||
//
|
||||
EXPORT void _Unwind_SjLj_Register(struct _Unwind_FunctionContext* fc)
|
||||
{
|
||||
fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(fc);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called at end of each function that catches exceptions
|
||||
//
|
||||
EXPORT void _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext* fc)
|
||||
{
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase1(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1: initial function-context=%p\n", c);
|
||||
|
||||
// walk each frame looking for a place to stop
|
||||
for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
|
||||
|
||||
// check for no more frames
|
||||
if ( c == NULL ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): reached bottom => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1: function-context=%p\n", c);
|
||||
// if there is a personality routine, ask it if it will want to stop at this frame
|
||||
if ( c->personality != NULL ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, c->personality);
|
||||
_Unwind_Reason_Code personalityResult = (*c->personality)(1, _UA_SEARCH_PHASE,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)c);
|
||||
switch ( personalityResult ) {
|
||||
case _URC_HANDLER_FOUND:
|
||||
// found a catch clause or locals that need destructing in this frame
|
||||
// stop search and remember function context
|
||||
handlerNotFound = false;
|
||||
exception_object->private_2 = (uintptr_t)c;
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
|
||||
return _URC_NO_REASON;
|
||||
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
// continue unwinding
|
||||
break;
|
||||
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase2(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
|
||||
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
while ( true ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2s(ex_ojb=%p): function-context=%p\n", exception_object, c);
|
||||
|
||||
// check for no more frames
|
||||
if ( c == NULL ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if ( c->personality != NULL ) {
|
||||
_Unwind_Action action = _UA_CLEANUP_PHASE;
|
||||
if ( (uintptr_t)c == exception_object->private_2 )
|
||||
action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
|
||||
_Unwind_Reason_Code personalityResult = (*c->personality)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)c);
|
||||
switch ( personalityResult ) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
// continue unwinding
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
if ( (uintptr_t)c == exception_object->private_2 ) {
|
||||
// phase 1 said we would stop at this frame, but we did not...
|
||||
ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
|
||||
}
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT, will resume at landing pad %p\n", exception_object, c->jbuf[1]);
|
||||
// personality routine says to transfer control to landing pad
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(c);
|
||||
__builtin_longjmp(c->jbuf, 1);
|
||||
// unw_resume() only returns if there was an error
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
c = c->prev;
|
||||
}
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase2_forced(struct _Unwind_Exception* exception_object,
|
||||
_Unwind_Stop_Fn stop, void* stop_parameter)
|
||||
{
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
_Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
|
||||
while ( true ) {
|
||||
|
||||
// get next frame (skip over first which is _Unwind_RaiseException)
|
||||
if ( c == NULL ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
// call stop function at each frame
|
||||
_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
|
||||
_Unwind_Reason_Code stopResult = (*stop)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)c, stop_parameter);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
|
||||
if ( stopResult != _URC_NO_REASON ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if ( c->personality != NULL ) {
|
||||
__personality_routine p = (__personality_routine)c->personality;
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
|
||||
_Unwind_Reason_Code personalityResult = (*p)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)c);
|
||||
switch ( personalityResult ) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
// destructors called, continue unwinding
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
__Unwind_SjLj_SetTopOfFunctionStack(c);
|
||||
__builtin_longjmp(c->jbuf, 1);
|
||||
break;
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n",
|
||||
exception_object, personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
c = c->prev;
|
||||
}
|
||||
|
||||
// call stop function one last time and tell it we've reached the end of the stack
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
|
||||
_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
|
||||
(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)c, stop_parameter);
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by __cxa_throw. Only returns if there is a fatal error
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_SjLj_RaiseException(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SjLj_RaiseException(ex_obj=%p)\n", exception_object);
|
||||
|
||||
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing
|
||||
exception_object->private_1 = 0;
|
||||
exception_object->private_2 = 0;
|
||||
|
||||
// phase 1: the search phase
|
||||
_Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
|
||||
if ( phase1 != _URC_NO_REASON )
|
||||
return phase1;
|
||||
|
||||
// phase 2: the clean up phase
|
||||
return unwind_phase2(exception_object);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// When _Unwind_RaiseException() is in phase2, it hands control
|
||||
// to the personality function at each frame. The personality
|
||||
// may force a jump to a landing pad in that function, the landing
|
||||
// pad code may then call _Unwind_Resume() to continue with the
|
||||
// unwinding. Note: the call to _Unwind_Resume() is from compiler
|
||||
// geneated user code. All other _Unwind_* routines are called
|
||||
// by the C++ runtime __cxa_* routines.
|
||||
//
|
||||
// Re-throwing an exception is implemented by having the code call
|
||||
// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
|
||||
//
|
||||
EXPORT void _Unwind_SjLj_Resume(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object);
|
||||
|
||||
if ( exception_object->private_1 != 0 )
|
||||
unwind_phase2_forced(exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2);
|
||||
else
|
||||
unwind_phase2(exception_object);
|
||||
|
||||
// clients assume _Unwind_Resume() does not return, so all we can do is abort.
|
||||
ABORT("_Unwind_SjLj_Resume() can't return");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by __cxa_rethrow()
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1);
|
||||
// if this is non-forced and a stopping place was found, then this is a re-throw
|
||||
// call _Unwind_RaiseException() as if this was a new exception
|
||||
if ( exception_object->private_1 == 0 ) {
|
||||
return _Unwind_SjLj_RaiseException(exception_object);
|
||||
// should return if there is no catch clause, so that __cxa_rethrow can call std::terminate()
|
||||
}
|
||||
|
||||
// call through to _Unwind_Resume() which distiguishes between forced and regular exceptions
|
||||
_Unwind_SjLj_Resume(exception_object);
|
||||
ABORT("__Unwind_SjLj_Resume_or_Rethrow() called _Unwind_SjLj_Resume() which unexpectedly returned");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get LSDA for current frame
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context)
|
||||
{
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%0lX\n", context, ufc->lsda);
|
||||
return ufc->lsda;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get register values
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d)\n", context, index);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
return ufc->resumeParameters[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to alter register values
|
||||
//
|
||||
EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)\n", context, index, new_value);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
ufc->resumeParameters[index] = new_value;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get instruction pointer
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context)
|
||||
{
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%lX\n", context, ufc->resumeLocation+1);
|
||||
return ufc->resumeLocation+1;
|
||||
}
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get instruction pointer
|
||||
// ipBefore is a boolean that says if IP is already adjusted to be the call
|
||||
// site address. Normally IP is the return address.
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore)
|
||||
{
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
*ipBefore = 0;
|
||||
DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX\n", context, ipBefore, ufc->resumeLocation+1);
|
||||
return ufc->resumeLocation+1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to alter instruction pointer
|
||||
//
|
||||
EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0lX)\n", context, new_value);
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
ufc->resumeLocation = new_value-1;
|
||||
}
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to find the start of the function
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context)
|
||||
{
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p)\n", context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 if a foreign exception is caught
|
||||
//
|
||||
EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object);
|
||||
if ( exception_object->exception_cleanup != NULL )
|
||||
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get base address for data relative encodings
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context)
|
||||
{
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context);
|
||||
ABORT("_Unwind_GetDataRelBase() not implemented");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get base address for text relative encodings
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context)
|
||||
{
|
||||
// Not supported or needed for sjlj based unwinding
|
||||
DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context);
|
||||
ABORT("_Unwind_GetTextRelBase() not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler to get Call Frame Area for current frame
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_GetCFA(context=%p)\n", context);
|
||||
if ( context != NULL ) {
|
||||
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t)context;
|
||||
// setjmp/longjmp based exceptions don't have a true CFA
|
||||
// the SP in the jmpbuf is the closest approximation
|
||||
return (uintptr_t)ufc->jbuf[2];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if !FOR_DYLD && __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
//
|
||||
// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in earlier versions
|
||||
//
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
|
||||
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
|
||||
#endif // !FOR_DYLD
|
||||
|
||||
|
||||
#endif // __arm__
|
912
src/UnwindCursor.hpp
Normal file
912
src/UnwindCursor.hpp
Normal file
@ -0,0 +1,912 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2007-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
//
|
||||
// C++ interface to lower levels of libuwind
|
||||
//
|
||||
|
||||
#ifndef __UNWINDCURSOR_HPP__
|
||||
#define __UNWINDCURSOR_HPP__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <Availability.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
|
||||
#include "AddressSpace.hpp"
|
||||
#include "Registers.hpp"
|
||||
#include "DwarfInstructions.hpp"
|
||||
#include "CompactUnwinder.hpp"
|
||||
#include "InternalMacros.h"
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#define KEYMGR_SUPPPORT 1
|
||||
#else
|
||||
#define KEYMGR_SUPPPORT 0
|
||||
#endif
|
||||
|
||||
|
||||
#if KEYMGR_SUPPPORT
|
||||
// private keymgr stuff
|
||||
#define KEYMGR_GCC3_DW2_OBJ_LIST 302
|
||||
extern "C" {
|
||||
extern void _keymgr_set_and_unlock_processwide_ptr(int key, void* ptr);
|
||||
extern void* _keymgr_get_and_lock_processwide_ptr(int key);
|
||||
};
|
||||
|
||||
// undocumented libgcc "struct object"
|
||||
struct libgcc_object
|
||||
{
|
||||
void* start;
|
||||
void* unused1;
|
||||
void* unused2;
|
||||
void* fde;
|
||||
unsigned long encoding;
|
||||
void* fde_end;
|
||||
libgcc_object* next;
|
||||
};
|
||||
|
||||
// undocumented libgcc "struct km_object_info" referenced by KEYMGR_GCC3_DW2_OBJ_LIST
|
||||
struct libgcc_object_info {
|
||||
struct libgcc_object* seen_objects;
|
||||
struct libgcc_object* unseen_objects;
|
||||
unsigned spare[2];
|
||||
};
|
||||
#endif // KEYMGR_SUPPPORT
|
||||
|
||||
|
||||
|
||||
namespace libunwind {
|
||||
|
||||
#if !FOR_DYLD
|
||||
template <typename A>
|
||||
class DwarfFDECache
|
||||
{
|
||||
public:
|
||||
typedef typename A::pint_t pint_t;
|
||||
static pint_t findFDE(pint_t mh, pint_t pc);
|
||||
static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
|
||||
static void removeAllIn(pint_t mh);
|
||||
static void iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
|
||||
private:
|
||||
static void dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide);
|
||||
|
||||
struct entry { pint_t mh; pint_t ip_start; pint_t ip_end; pint_t fde; };
|
||||
|
||||
// these fields are all static to avoid needing an initializer
|
||||
// there is only one instance of this class per process
|
||||
static pthread_rwlock_t fgLock;
|
||||
static bool fgRegisteredForDyldUnloads;
|
||||
// can't use std::vector<> here because this code must live in libSystem.dylib (which is below libstdc++.dylib)
|
||||
static entry* fgBuffer;
|
||||
static entry* fgBufferUsed;
|
||||
static entry* fgBufferEnd;
|
||||
static entry fgInitialBuffer[64];
|
||||
};
|
||||
|
||||
template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBuffer = fgInitialBuffer;
|
||||
template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferUsed = fgInitialBuffer;
|
||||
template <typename A> typename DwarfFDECache<A>::entry* DwarfFDECache<A>::fgBufferEnd = &fgInitialBuffer[64];
|
||||
template <typename A> typename DwarfFDECache<A>::entry DwarfFDECache<A>::fgInitialBuffer[64];
|
||||
|
||||
template <typename A>
|
||||
pthread_rwlock_t DwarfFDECache<A>::fgLock = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
template <typename A>
|
||||
bool DwarfFDECache<A>::fgRegisteredForDyldUnloads = false;
|
||||
|
||||
|
||||
template <typename A>
|
||||
typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc)
|
||||
{
|
||||
pint_t result = NULL;
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_rdlock(&fgLock));
|
||||
for(entry* p=fgBuffer; p < fgBufferUsed; ++p) {
|
||||
if ( (mh == p->mh) || (mh == 0) ) {
|
||||
if ( (p->ip_start <= pc) && (pc < p->ip_end) ) {
|
||||
result = p->fde;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
|
||||
//fprintf(stderr, "DwarfFDECache::findFDE(mh=0x%llX, pc=0x%llX) => 0x%llX\n", (uint64_t)mh, (uint64_t)pc, (uint64_t)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename A>
|
||||
void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde)
|
||||
{
|
||||
//fprintf(stderr, "DwarfFDECache::add(mh=0x%llX, ip_start=0x%llX, ip_end=0x%llX, fde=0x%llX) pthread=%p\n",
|
||||
// (uint64_t)mh, (uint64_t)ip_start, (uint64_t)ip_end, (uint64_t)fde, pthread_self());
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
|
||||
if ( fgBufferUsed >= fgBufferEnd ) {
|
||||
int oldSize = fgBufferEnd - fgBuffer;
|
||||
int newSize = oldSize*4;
|
||||
entry* newBuffer = (entry*)malloc(newSize*sizeof(entry)); // can't use operator new in libSystem.dylib
|
||||
memcpy(newBuffer, fgBuffer, oldSize*sizeof(entry));
|
||||
//fprintf(stderr, "DwarfFDECache::add() growing buffer to %d\n", newSize);
|
||||
if ( fgBuffer != fgInitialBuffer )
|
||||
free(fgBuffer);
|
||||
fgBuffer = newBuffer;
|
||||
fgBufferUsed = &newBuffer[oldSize];
|
||||
fgBufferEnd = &newBuffer[newSize];
|
||||
}
|
||||
fgBufferUsed->mh = mh;
|
||||
fgBufferUsed->ip_start = ip_start;
|
||||
fgBufferUsed->ip_end = ip_end;
|
||||
fgBufferUsed->fde = fde;
|
||||
++fgBufferUsed;
|
||||
if ( !fgRegisteredForDyldUnloads ) {
|
||||
_dyld_register_func_for_remove_image(&dyldUnloadHook);
|
||||
fgRegisteredForDyldUnloads = true;
|
||||
}
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename A>
|
||||
void DwarfFDECache<A>::removeAllIn(pint_t mh)
|
||||
{
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
|
||||
entry* d=fgBuffer;
|
||||
for(const entry* s=fgBuffer; s < fgBufferUsed; ++s) {
|
||||
if ( s->mh != mh ) {
|
||||
if ( d != s )
|
||||
*d = *s;
|
||||
++d;
|
||||
}
|
||||
}
|
||||
fgBufferUsed = d;
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
|
||||
}
|
||||
|
||||
|
||||
template <typename A>
|
||||
void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header* mh, intptr_t vmaddr_slide)
|
||||
{
|
||||
removeAllIn((pint_t)mh);
|
||||
}
|
||||
|
||||
template <typename A>
|
||||
void DwarfFDECache<A>::iterateCacheEntries(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh))
|
||||
{
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_wrlock(&fgLock));
|
||||
for(entry* p=fgBuffer; p < fgBufferUsed; ++p) {
|
||||
(*func)(p->ip_start, p->ip_end, p->fde, p->mh);
|
||||
}
|
||||
DEBUG_LOG_NON_ZERO(::pthread_rwlock_unlock(&fgLock));
|
||||
}
|
||||
#endif // !FOR_DYLD
|
||||
|
||||
|
||||
|
||||
|
||||
#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionHeader {
|
||||
public:
|
||||
UnwindSectionHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t version() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, version)); }
|
||||
uint32_t commonEncodingsArraySectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArraySectionOffset)); }
|
||||
uint32_t commonEncodingsArrayCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, commonEncodingsArrayCount)); }
|
||||
uint32_t personalityArraySectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArraySectionOffset)); }
|
||||
uint32_t personalityArrayCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, personalityArrayCount)); }
|
||||
uint32_t indexSectionOffset() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexSectionOffset)); }
|
||||
uint32_t indexCount() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_section_header, indexCount)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionIndexArray {
|
||||
public:
|
||||
UnwindSectionIndexArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, functionOffset)); }
|
||||
uint32_t secondLevelPagesSectionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, secondLevelPagesSectionOffset)); }
|
||||
uint32_t lsdaIndexArraySectionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_index_entry, index, lsdaIndexArraySectionOffset)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionRegularPageHeader {
|
||||
public:
|
||||
UnwindSectionRegularPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t kind() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_regular_second_level_page_header, kind)); }
|
||||
uint16_t entryPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryPageOffset)); }
|
||||
uint16_t entryCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_regular_second_level_page_header, entryCount)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionRegularArray {
|
||||
public:
|
||||
UnwindSectionRegularArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, functionOffset)); }
|
||||
uint32_t encoding(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionCompressedPageHeader {
|
||||
public:
|
||||
UnwindSectionCompressedPageHeader(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t kind() const INLINE { return fAddressSpace.get32(fAddr + offsetof(unwind_info_compressed_second_level_page_header, kind)); }
|
||||
uint16_t entryPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryPageOffset)); }
|
||||
uint16_t entryCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, entryCount)); }
|
||||
uint16_t encodingsPageOffset() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsPageOffset)); }
|
||||
uint16_t encodingsCount() const INLINE { return fAddressSpace.get16(fAddr + offsetof(unwind_info_compressed_second_level_page_header, encodingsCount)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionCompressedArray {
|
||||
public:
|
||||
UnwindSectionCompressedArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t functionOffset(int index) const INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); }
|
||||
uint16_t encodingIndex(int index) const INLINE { return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( fAddressSpace.get32(fAddr + index*sizeof(uint32_t)) ); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A>
|
||||
class UnwindSectionLsdaArray {
|
||||
public:
|
||||
UnwindSectionLsdaArray(A& addressSpace, typename A::pint_t addr) : fAddressSpace(addressSpace), fAddr(addr) {}
|
||||
|
||||
uint32_t functionOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, functionOffset)); }
|
||||
int32_t lsdaOffset(int index) const INLINE { return fAddressSpace.get32(fAddr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, index, lsdaOffset)); }
|
||||
private:
|
||||
A& fAddressSpace;
|
||||
typename A::pint_t fAddr;
|
||||
};
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
class UnwindCursor
|
||||
{
|
||||
public:
|
||||
UnwindCursor(unw_context_t* context, A& as);
|
||||
UnwindCursor(A& as, thread_t thread);
|
||||
virtual ~UnwindCursor() {}
|
||||
virtual bool validReg(int);
|
||||
virtual uint64_t getReg(int);
|
||||
virtual void setReg(int, uint64_t);
|
||||
virtual bool validFloatReg(int);
|
||||
virtual double getFloatReg(int);
|
||||
virtual void setFloatReg(int, double);
|
||||
virtual int step();
|
||||
virtual void getInfo(unw_proc_info_t*);
|
||||
virtual void jumpto();
|
||||
virtual const char* getRegisterName(int num);
|
||||
virtual bool isSignalFrame();
|
||||
virtual bool getFunctionName(char* buf, size_t bufLen, unw_word_t* offset);
|
||||
virtual void setInfoBasedOnIPRegister(bool isReturnAddress=false);
|
||||
|
||||
void operator delete(void* p, size_t size) {}
|
||||
|
||||
private:
|
||||
typedef typename A::pint_t pint_t;
|
||||
typedef uint32_t EncodedUnwindInfo;
|
||||
|
||||
bool getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart);
|
||||
bool getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE);
|
||||
|
||||
int stepWithDwarfFDE()
|
||||
{ return DwarfInstructions<A,R>::stepWithDwarf(fAddressSpace, this->getReg(UNW_REG_IP), fInfo.unwind_info, fRegisters); }
|
||||
|
||||
int stepWithCompactEncoding() { R dummy; return stepWithCompactEncoding(dummy); }
|
||||
int stepWithCompactEncoding(Registers_x86_64&)
|
||||
{ return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); }
|
||||
int stepWithCompactEncoding(Registers_x86&)
|
||||
{ return CompactUnwinder_x86<A>::stepWithCompactEncoding(fInfo.format, fInfo.start_ip, fAddressSpace, fRegisters); }
|
||||
int stepWithCompactEncoding(Registers_ppc&)
|
||||
{ return UNW_EINVAL; }
|
||||
|
||||
#if FOR_DYLD
|
||||
#if __ppc__
|
||||
bool mustUseDwarf() const { return true; }
|
||||
#else
|
||||
bool mustUseDwarf() const { return false; }
|
||||
#endif
|
||||
#else
|
||||
bool mustUseDwarf() const { R dummy; uint32_t offset; return dwarfWithOffset(dummy, offset); }
|
||||
#endif
|
||||
|
||||
bool dwarfWithOffset(uint32_t& offset) const { R dummy; return dwarfWithOffset(dummy, offset); }
|
||||
bool dwarfWithOffset(Registers_x86_64&, uint32_t& offset) const {
|
||||
if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF ) {
|
||||
offset = (fInfo.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
|
||||
return true;
|
||||
}
|
||||
#if SUPPORT_OLD_BINARIES
|
||||
if ( (fInfo.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_COMPATIBILITY ) {
|
||||
if ( (fInfo.format & UNWIND_X86_64_CASE_MASK) == UNWIND_X86_64_UNWIND_REQUIRES_DWARF ) {
|
||||
offset = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
bool dwarfWithOffset(Registers_x86&, uint32_t& offset) const {
|
||||
if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF ) {
|
||||
offset = (fInfo.format & UNWIND_X86_DWARF_SECTION_OFFSET);
|
||||
return true;
|
||||
}
|
||||
#if SUPPORT_OLD_BINARIES
|
||||
if ( (fInfo.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_COMPATIBILITY ) {
|
||||
if ( (fInfo.format & UNWIND_X86_CASE_MASK) == UNWIND_X86_UNWIND_REQUIRES_DWARF ) {
|
||||
offset = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
bool dwarfWithOffset(Registers_ppc&, uint32_t& offset) const { return true; }
|
||||
|
||||
|
||||
compact_unwind_encoding_t dwarfEncoding() const { R dummy; return dwarfEncoding(dummy); }
|
||||
compact_unwind_encoding_t dwarfEncoding(Registers_x86_64&) const { return UNWIND_X86_64_MODE_DWARF; }
|
||||
compact_unwind_encoding_t dwarfEncoding(Registers_x86&) const { return UNWIND_X86_MODE_DWARF; }
|
||||
compact_unwind_encoding_t dwarfEncoding(Registers_ppc&) const { return 0; }
|
||||
|
||||
unw_proc_info_t fInfo;
|
||||
R fRegisters;
|
||||
A& fAddressSpace;
|
||||
bool fUnwindInfoMissing;
|
||||
bool fIsSignalFrame;
|
||||
};
|
||||
|
||||
typedef UnwindCursor<LocalAddressSpace,Registers_x86> AbstractUnwindCursor;
|
||||
|
||||
template <typename A, typename R>
|
||||
UnwindCursor<A,R>::UnwindCursor(unw_context_t* context, A& as)
|
||||
: fRegisters(context), fAddressSpace(as), fUnwindInfoMissing(false), fIsSignalFrame(false)
|
||||
{
|
||||
COMPILE_TIME_ASSERT( sizeof(UnwindCursor<A,R>) < sizeof(unw_cursor_t) );
|
||||
|
||||
bzero(&fInfo, sizeof(fInfo));
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
UnwindCursor<A,R>::UnwindCursor(A& as, thread_t thread)
|
||||
: fAddressSpace(as), fUnwindInfoMissing(false), fIsSignalFrame(false)
|
||||
{
|
||||
bzero(&fInfo, sizeof(fInfo));
|
||||
// FIXME
|
||||
// fill in fRegisters from thread
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::validReg(int regNum)
|
||||
{
|
||||
return fRegisters.validRegister(regNum);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
uint64_t UnwindCursor<A,R>::getReg(int regNum)
|
||||
{
|
||||
return fRegisters.getRegister(regNum);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
void UnwindCursor<A,R>::setReg(int regNum, uint64_t value)
|
||||
{
|
||||
fRegisters.setRegister(regNum, value);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::validFloatReg(int regNum)
|
||||
{
|
||||
return fRegisters.validFloatRegister(regNum);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
double UnwindCursor<A,R>::getFloatReg(int regNum)
|
||||
{
|
||||
return fRegisters.getFloatRegister(regNum);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
void UnwindCursor<A,R>::setFloatReg(int regNum, double value)
|
||||
{
|
||||
fRegisters.setFloatRegister(regNum, value);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
void UnwindCursor<A,R>::jumpto()
|
||||
{
|
||||
fRegisters.jumpto();
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
const char* UnwindCursor<A,R>::getRegisterName(int regNum)
|
||||
{
|
||||
return fRegisters.getRegisterName(regNum);
|
||||
}
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::isSignalFrame()
|
||||
{
|
||||
return fIsSignalFrame;
|
||||
}
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::getInfoFromDwarfSection(pint_t pc, pint_t mh, pint_t ehSectionStart, uint32_t sectionLength, uint32_t sectionOffsetOfFDE)
|
||||
{
|
||||
typename CFI_Parser<A>::FDE_Info fdeInfo;
|
||||
typename CFI_Parser<A>::CIE_Info cieInfo;
|
||||
bool foundFDE = false;
|
||||
bool foundInCache = false;
|
||||
// if compact encoding table gave offset into dwarf section, go directly there
|
||||
if ( sectionOffsetOfFDE != 0 ) {
|
||||
foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, ehSectionStart+sectionOffsetOfFDE, &fdeInfo, &cieInfo);
|
||||
}
|
||||
#if !FOR_DYLD
|
||||
if ( !foundFDE ) {
|
||||
// otherwise, search cache of previously found FDEs
|
||||
pint_t cachedFDE = DwarfFDECache<A>::findFDE(mh, pc);
|
||||
//fprintf(stderr, "getInfoFromDwarfSection(pc=0x%llX) cachedFDE=0x%llX\n", (uint64_t)pc, (uint64_t)cachedFDE);
|
||||
if ( cachedFDE != 0 ) {
|
||||
foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, cachedFDE, &fdeInfo, &cieInfo);
|
||||
foundInCache = foundFDE;
|
||||
//fprintf(stderr, "cachedFDE=0x%llX, foundInCache=%d\n", (uint64_t)cachedFDE, foundInCache);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if ( !foundFDE ) {
|
||||
// still not found, do full scan of __eh_frame section
|
||||
foundFDE = CFI_Parser<A>::findFDE(fAddressSpace, pc, ehSectionStart, sectionLength, 0, &fdeInfo, &cieInfo);
|
||||
}
|
||||
if ( foundFDE ) {
|
||||
typename CFI_Parser<A>::PrologInfo prolog;
|
||||
if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
|
||||
// save off parsed FDE info
|
||||
fInfo.start_ip = fdeInfo.pcStart;
|
||||
fInfo.end_ip = fdeInfo.pcEnd;
|
||||
fInfo.lsda = fdeInfo.lsda;
|
||||
fInfo.handler = cieInfo.personality;
|
||||
fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function
|
||||
fInfo.flags = 0;
|
||||
fInfo.format = dwarfEncoding();
|
||||
fInfo.unwind_info = fdeInfo.fdeStart;
|
||||
fInfo.unwind_info_size = fdeInfo.fdeLength;
|
||||
fInfo.extra = (unw_word_t)mh;
|
||||
if ( !foundInCache && (sectionOffsetOfFDE == 0) ) {
|
||||
// don't add to cache entries the compact encoding table can find quickly
|
||||
//fprintf(stderr, "getInfoFromDwarfSection(pc=0x%0llX), mh=0x%llX, start_ip=0x%0llX, fde=0x%0llX, personality=0x%0llX\n",
|
||||
// (uint64_t)pc, (uint64_t)mh, fInfo.start_ip, fInfo.unwind_info, fInfo.handler);
|
||||
#if !FOR_DYLD
|
||||
DwarfFDECache<A>::add(mh, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//DEBUG_MESSAGE("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::getInfoFromCompactEncodingSection(pint_t pc, pint_t mh, pint_t unwindSectionStart)
|
||||
{
|
||||
const bool log = false;
|
||||
if ( log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", (uint64_t)pc, (uint64_t)mh);
|
||||
|
||||
const UnwindSectionHeader<A> sectionHeader(fAddressSpace, unwindSectionStart);
|
||||
if ( sectionHeader.version() != UNWIND_SECTION_VERSION )
|
||||
return false;
|
||||
|
||||
// do a binary search of top level index to find page with unwind info
|
||||
uint32_t targetFunctionOffset = pc - mh;
|
||||
const UnwindSectionIndexArray<A> topIndex(fAddressSpace, unwindSectionStart + sectionHeader.indexSectionOffset());
|
||||
uint32_t low = 0;
|
||||
uint32_t high = sectionHeader.indexCount();
|
||||
const uint32_t last = high - 1;
|
||||
while ( low < high ) {
|
||||
uint32_t mid = (low + high)/2;
|
||||
//if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", mid, low, high, topIndex.functionOffset(mid));
|
||||
if ( topIndex.functionOffset(mid) <= targetFunctionOffset ) {
|
||||
if ( (mid == last) || (topIndex.functionOffset(mid+1) > targetFunctionOffset) ) {
|
||||
low = mid;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
|
||||
const uint32_t firstLevelNextPageFunctionOffset = topIndex.functionOffset(low+1);
|
||||
const pint_t secondLevelAddr = unwindSectionStart+topIndex.secondLevelPagesSectionOffset(low);
|
||||
const pint_t lsdaArrayStartAddr = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low);
|
||||
const pint_t lsdaArrayEndAddr = unwindSectionStart+topIndex.lsdaIndexArraySectionOffset(low+1);
|
||||
if ( log ) fprintf(stderr, "\tfirst level search for result index=%d to secondLevelAddr=0x%llX\n",
|
||||
low, (uint64_t)secondLevelAddr);
|
||||
// do a binary search of second level page index
|
||||
uint32_t encoding = 0;
|
||||
pint_t funcStart = 0;
|
||||
pint_t funcEnd = 0;
|
||||
pint_t lsda = 0;
|
||||
pint_t personality = 0;
|
||||
uint32_t pageKind = fAddressSpace.get32(secondLevelAddr);
|
||||
if ( pageKind == UNWIND_SECOND_LEVEL_REGULAR ) {
|
||||
// regular page
|
||||
UnwindSectionRegularPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr);
|
||||
UnwindSectionRegularArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset());
|
||||
// binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset
|
||||
if ( log ) fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in regular page starting at secondLevelAddr=0x%llX\n",
|
||||
(uint64_t)targetFunctionOffset, (uint64_t)secondLevelAddr);
|
||||
uint32_t low = 0;
|
||||
uint32_t high = pageHeader.entryCount();
|
||||
while ( low < high ) {
|
||||
uint32_t mid = (low + high)/2;
|
||||
if ( pageIndex.functionOffset(mid) <= targetFunctionOffset ) {
|
||||
if ( mid == (uint32_t)(pageHeader.entryCount()-1) ) {
|
||||
// at end of table
|
||||
low = mid;
|
||||
funcEnd = firstLevelNextPageFunctionOffset + mh;
|
||||
break;
|
||||
}
|
||||
else if ( pageIndex.functionOffset(mid+1) > targetFunctionOffset ) {
|
||||
// next is too big, so we found it
|
||||
low = mid;
|
||||
funcEnd = pageIndex.functionOffset(low+1) + mh;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
encoding = pageIndex.encoding(low);
|
||||
funcStart = pageIndex.functionOffset(low) + mh;
|
||||
if ( pc < funcStart ) {
|
||||
if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd);
|
||||
return false;
|
||||
}
|
||||
if ( pc > funcEnd ) {
|
||||
if ( log ) fprintf(stderr, "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart, (uint64_t)funcEnd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( pageKind == UNWIND_SECOND_LEVEL_COMPRESSED ) {
|
||||
// compressed page
|
||||
UnwindSectionCompressedPageHeader<A> pageHeader(fAddressSpace, secondLevelAddr);
|
||||
UnwindSectionCompressedArray<A> pageIndex(fAddressSpace, secondLevelAddr + pageHeader.entryPageOffset());
|
||||
const uint32_t targetFunctionPageOffset = targetFunctionOffset - firstLevelFunctionOffset;
|
||||
// binary search looks for entry with e where index[e].offset <= pc < index[e+1].offset
|
||||
if ( log ) fprintf(stderr, "\tbinary search of compressed page starting at secondLevelAddr=0x%llX\n", (uint64_t)secondLevelAddr);
|
||||
uint32_t low = 0;
|
||||
const uint32_t last = pageHeader.entryCount() - 1;
|
||||
uint32_t high = pageHeader.entryCount();
|
||||
while ( low < high ) {
|
||||
uint32_t mid = (low + high)/2;
|
||||
if ( pageIndex.functionOffset(mid) <= targetFunctionPageOffset ) {
|
||||
if ( (mid == last) || (pageIndex.functionOffset(mid+1) > targetFunctionPageOffset) ) {
|
||||
low = mid;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset + mh;
|
||||
if ( low < last )
|
||||
funcEnd = pageIndex.functionOffset(low+1) + firstLevelFunctionOffset + mh;
|
||||
else
|
||||
funcEnd = firstLevelNextPageFunctionOffset + mh;
|
||||
if ( pc < funcStart ) {
|
||||
DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcStart=0x%llX\n", (uint64_t)pc, (uint64_t)funcStart);
|
||||
return false;
|
||||
}
|
||||
if ( pc > funcEnd ) {
|
||||
DEBUG_MESSAGE("malformed __unwind_info, pc=0x%llX not in second level compressed unwind table. funcEnd=0x%llX\n", (uint64_t)pc, (uint64_t)funcEnd);
|
||||
return false;
|
||||
}
|
||||
uint16_t encodingIndex = pageIndex.encodingIndex(low);
|
||||
if ( encodingIndex < sectionHeader.commonEncodingsArrayCount() ) {
|
||||
// encoding is in common table in section header
|
||||
encoding = fAddressSpace.get32(unwindSectionStart+sectionHeader.commonEncodingsArraySectionOffset()+encodingIndex*sizeof(uint32_t));
|
||||
}
|
||||
else {
|
||||
// encoding is in page specific table
|
||||
uint16_t pageEncodingIndex = encodingIndex-sectionHeader.commonEncodingsArrayCount();
|
||||
encoding = fAddressSpace.get32(secondLevelAddr+pageHeader.encodingsPageOffset()+pageEncodingIndex*sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_MESSAGE("malformed __unwind_info at 0x%0llX bad second level page\n", (uint64_t)unwindSectionStart);
|
||||
return false;
|
||||
}
|
||||
|
||||
// look up LSDA, if encoding says function has one
|
||||
if ( encoding & UNWIND_HAS_LSDA ) {
|
||||
UnwindSectionLsdaArray<A> lsdaIndex(fAddressSpace, lsdaArrayStartAddr);
|
||||
uint32_t funcStartOffset = funcStart - mh;
|
||||
uint32_t low = 0;
|
||||
uint32_t high = (lsdaArrayEndAddr-lsdaArrayStartAddr)/sizeof(unwind_info_section_header_lsda_index_entry);
|
||||
// binary search looks for entry with exact match for functionOffset
|
||||
if ( log ) fprintf(stderr, "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", funcStartOffset);
|
||||
while ( low < high ) {
|
||||
uint32_t mid = (low + high)/2;
|
||||
if ( lsdaIndex.functionOffset(mid) == funcStartOffset ) {
|
||||
lsda = lsdaIndex.lsdaOffset(mid) + mh;
|
||||
break;
|
||||
}
|
||||
else if ( lsdaIndex.functionOffset(mid) < funcStartOffset ) {
|
||||
low = mid+1;
|
||||
}
|
||||
else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
if ( lsda == 0 ) {
|
||||
DEBUG_MESSAGE("found encoding 0x%08X with HAS_LSDA bit set for pc=0x%0llX, but lsda table has no entry\n", encoding, (uint64_t)pc);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// extact personality routine, if encoding says function has one
|
||||
uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> (__builtin_ctz(UNWIND_PERSONALITY_MASK));
|
||||
if ( personalityIndex != 0 ) {
|
||||
--personalityIndex; // change 1-based to zero-based index
|
||||
if ( personalityIndex > sectionHeader.personalityArrayCount() ) {
|
||||
DEBUG_MESSAGE("found encoding 0x%08X with personality index %d, but personality table has only %d entires\n",
|
||||
encoding, personalityIndex, sectionHeader.personalityArrayCount());
|
||||
return false;
|
||||
}
|
||||
int32_t personalityDelta = fAddressSpace.get32(unwindSectionStart+sectionHeader.personalityArraySectionOffset()+personalityIndex*sizeof(uint32_t));
|
||||
pint_t personalityPointer = personalityDelta + mh;
|
||||
personality = fAddressSpace.getP(personalityPointer);
|
||||
if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), personalityDelta=0x%08X, personality=0x%08llX\n",
|
||||
(uint64_t)pc, personalityDelta, (uint64_t)personality);
|
||||
}
|
||||
|
||||
if (log ) fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
|
||||
(uint64_t)pc, encoding, (uint64_t)lsda, (uint64_t)funcStart);
|
||||
fInfo.start_ip = funcStart;
|
||||
fInfo.end_ip = funcEnd;
|
||||
fInfo.lsda = lsda;
|
||||
fInfo.handler = personality;
|
||||
fInfo.gp = 0;
|
||||
fInfo.flags = 0;
|
||||
fInfo.format = encoding;
|
||||
fInfo.unwind_info = 0;
|
||||
fInfo.unwind_info_size = 0;
|
||||
fInfo.extra = mh;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
void UnwindCursor<A,R>::setInfoBasedOnIPRegister(bool isReturnAddress)
|
||||
{
|
||||
pint_t pc = this->getReg(UNW_REG_IP);
|
||||
|
||||
// if the last line of a function is a "throw" the compile sometimes
|
||||
// emits no instructions after the call to __cxa_throw. This means
|
||||
// the return address is actually the start of the next function.
|
||||
// To disambiguate this, back up the pc when we know it is a return
|
||||
// address.
|
||||
if ( isReturnAddress )
|
||||
--pc;
|
||||
|
||||
// ask address space object to find unwind sections for this pc
|
||||
pint_t mh;
|
||||
pint_t dwarfStart;
|
||||
pint_t dwarfLength;
|
||||
pint_t compactStart;
|
||||
if ( fAddressSpace.findUnwindSections(pc, mh, dwarfStart, dwarfLength, compactStart) ) {
|
||||
// if there is a compact unwind encoding table, look there first
|
||||
if ( compactStart != 0 ) {
|
||||
if ( this->getInfoFromCompactEncodingSection(pc, mh, compactStart) ) {
|
||||
#if !FOR_DYLD
|
||||
// found info in table, done unless encoding says to use dwarf
|
||||
uint32_t offsetInDwarfSection;
|
||||
if ( (dwarfStart != 0) && dwarfWithOffset(offsetInDwarfSection) ) {
|
||||
if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, offsetInDwarfSection) ) {
|
||||
// found info in dwarf, done
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// if unwind table has entry, but entry says there is no unwind info, note that
|
||||
if ( fInfo.format == 0 )
|
||||
fUnwindInfoMissing = true;
|
||||
|
||||
// old compact encoding
|
||||
if ( !mustUseDwarf() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !FOR_DYLD || __ppc__
|
||||
// if there is dwarf unwind info, look there next
|
||||
if ( dwarfStart != 0 ) {
|
||||
if ( this->getInfoFromDwarfSection(pc, mh, dwarfStart, dwarfLength, 0) ) {
|
||||
// found info in dwarf, done
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !FOR_DYLD
|
||||
// the PC is not in code loaded by dyld, look through __register_frame() registered FDEs
|
||||
pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
|
||||
if ( cachedFDE != 0 ) {
|
||||
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
|
||||
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
|
||||
const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, cachedFDE, &fdeInfo, &cieInfo);
|
||||
if ( msg == NULL ) {
|
||||
typename CFI_Parser<A>::PrologInfo prolog;
|
||||
if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
|
||||
// save off parsed FDE info
|
||||
fInfo.start_ip = fdeInfo.pcStart;
|
||||
fInfo.end_ip = fdeInfo.pcEnd;
|
||||
fInfo.lsda = fdeInfo.lsda;
|
||||
fInfo.handler = cieInfo.personality;
|
||||
fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function
|
||||
fInfo.flags = 0;
|
||||
fInfo.format = dwarfEncoding();
|
||||
fInfo.unwind_info = fdeInfo.fdeStart;
|
||||
fInfo.unwind_info_size = fdeInfo.fdeLength;
|
||||
fInfo.extra = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if KEYMGR_SUPPPORT
|
||||
// lastly check for old style keymgr registration of dynamically generated FDEs
|
||||
// acquire exclusive access to libgcc_object_info
|
||||
libgcc_object_info* head = (libgcc_object_info*)_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
|
||||
if ( head != NULL ) {
|
||||
// look at each FDE in keymgr
|
||||
for (libgcc_object* ob = head->unseen_objects; ob != NULL; ob = ob->next) {
|
||||
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
|
||||
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
|
||||
const char* msg = CFI_Parser<A>::decodeFDE(fAddressSpace, (pint_t)ob->fde, &fdeInfo, &cieInfo);
|
||||
if ( msg == NULL ) {
|
||||
// see if this FDE is for a function that includes the pc we are looking for
|
||||
if ( (fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd) ) {
|
||||
typename CFI_Parser<A>::PrologInfo prolog;
|
||||
if ( CFI_Parser<A>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
|
||||
// save off parsed FDE info
|
||||
fInfo.start_ip = fdeInfo.pcStart;
|
||||
fInfo.end_ip = fdeInfo.pcEnd;
|
||||
fInfo.lsda = fdeInfo.lsda;
|
||||
fInfo.handler = cieInfo.personality;
|
||||
fInfo.gp = prolog.spExtraArgSize; // some frameless functions need SP altered when resuming in function
|
||||
fInfo.flags = 0;
|
||||
fInfo.format = dwarfEncoding();
|
||||
fInfo.unwind_info = fdeInfo.fdeStart;
|
||||
fInfo.unwind_info_size = fdeInfo.fdeLength;
|
||||
fInfo.extra = 0;
|
||||
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// release libgcc_object_info
|
||||
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
|
||||
#endif // KEYMGR_SUPPPORT
|
||||
|
||||
#endif
|
||||
|
||||
// no unwind info, flag that we can't reliable unwind
|
||||
fUnwindInfoMissing = true;
|
||||
}
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
int UnwindCursor<A,R>::step()
|
||||
{
|
||||
// bottom of stack is defined as when no more unwind info
|
||||
if ( fUnwindInfoMissing )
|
||||
return UNW_STEP_END;
|
||||
|
||||
// apply unwinding to register set
|
||||
int result;
|
||||
if ( this->mustUseDwarf() )
|
||||
result = this->stepWithDwarfFDE();
|
||||
else
|
||||
result = this->stepWithCompactEncoding();
|
||||
|
||||
// update info based on new PC
|
||||
if ( result == UNW_STEP_SUCCESS ) {
|
||||
this->setInfoBasedOnIPRegister(true);
|
||||
if ( fUnwindInfoMissing )
|
||||
return UNW_STEP_END;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
void UnwindCursor<A,R>::getInfo(unw_proc_info_t* info)
|
||||
{
|
||||
*info = fInfo;
|
||||
}
|
||||
|
||||
|
||||
template <typename A, typename R>
|
||||
bool UnwindCursor<A,R>::getFunctionName(char* buf, size_t bufLen, unw_word_t* offset)
|
||||
{
|
||||
return fAddressSpace.findFunctionName(this->getReg(UNW_REG_IP), buf, bufLen, offset);
|
||||
}
|
||||
|
||||
}; // namespace libunwind
|
||||
|
||||
|
||||
#endif // __UNWINDCURSOR_HPP__
|
||||
|
||||
|
||||
|
||||
|
306
src/UnwindLevel1-gcc-ext.c
Normal file
306
src/UnwindLevel1-gcc-ext.c
Normal file
@ -0,0 +1,306 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2008-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
* Implements gcc extensions to the C++ ABI Exception Handling Level 1 as documented at:
|
||||
* <http://www.codesourcery.com/cxx-abi/abi-eh.html>
|
||||
* using libunwind
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
#include "unwind.h"
|
||||
#include "libunwind_priv.h"
|
||||
#include "InternalMacros.h"
|
||||
|
||||
|
||||
#if __ppc__ || __i386__ || __x86_64__
|
||||
|
||||
//
|
||||
// Called by __cxa_rethrow()
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld\n", exception_object, exception_object->private_1);
|
||||
// if this is non-forced and a stopping place was found, then this is a re-throw
|
||||
// call _Unwind_RaiseException() as if this was a new exception
|
||||
if ( exception_object->private_1 == 0 ) {
|
||||
return _Unwind_RaiseException(exception_object);
|
||||
// should return if there is no catch clause, so that __cxa_rethrow can call std::terminate()
|
||||
}
|
||||
|
||||
// call through to _Unwind_Resume() which distiguishes between forced and regular exceptions
|
||||
_Unwind_Resume(exception_object);
|
||||
ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException() which unexpectedly returned");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get base address for data relative encodings
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context* context)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_GetDataRelBase(context=%p)\n", context);
|
||||
ABORT("_Unwind_GetDataRelBase() not implemented");
|
||||
}
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get base address for text relative encodings
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context* context)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_GetTextRelBase(context=%p)\n", context);
|
||||
ABORT("_Unwind_GetTextRelBase() not implemented");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Scans unwind information to find the function that contains the
|
||||
// specified code address "pc".
|
||||
//
|
||||
EXPORT void* _Unwind_FindEnclosingFunction(void* pc)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_FindEnclosingFunction(pc=%p)\n", pc);
|
||||
// This is slow, but works.
|
||||
// We create an unwind cursor then alter the IP to be pc
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_proc_info_t info;
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long)pc);
|
||||
if ( unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS )
|
||||
return (void*)(long)info.start_ip;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Walk every frame and call trace function at each one. If trace function
|
||||
// returns anything other than _URC_NO_REASON, then walk is terminated.
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void* ref)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
|
||||
DEBUG_PRINT_API("_Unwind_Backtrace(callback=%p)\n", callback);
|
||||
|
||||
// walk each frame
|
||||
while ( true ) {
|
||||
|
||||
// ask libuwind to get next frame (skip over first frame which is _Unwind_Backtrace())
|
||||
if ( unw_step(&cursor) <= 0 ) {
|
||||
DEBUG_PRINT_UNWINDING(" _backtrace: ended because cursor reached bottom of stack, returning %d\n", _URC_END_OF_STACK);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
// debugging
|
||||
if ( DEBUG_PRINT_UNWINDING_TEST ) {
|
||||
char functionName[512];
|
||||
unw_proc_info_t frameInfo;
|
||||
unw_word_t offset;
|
||||
unw_get_proc_name(&cursor, functionName, 512, &offset);
|
||||
unw_get_proc_info(&cursor, &frameInfo);
|
||||
DEBUG_PRINT_UNWINDING(" _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n",
|
||||
frameInfo.start_ip, functionName, frameInfo.lsda, &cursor);
|
||||
}
|
||||
|
||||
// call trace function with this frame
|
||||
_Unwind_Reason_Code result = (*callback)((struct _Unwind_Context*)(&cursor), ref);
|
||||
if ( result != _URC_NO_REASON ) {
|
||||
DEBUG_PRINT_UNWINDING(" _backtrace: ended because callback returned %d\n", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Find dwarf unwind info for an address 'pc' in some function.
|
||||
//
|
||||
EXPORT const void* _Unwind_Find_FDE(const void* pc, struct dwarf_eh_bases* bases)
|
||||
{
|
||||
// This is slow, but works.
|
||||
// We create an unwind cursor then alter the IP to be pc
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_proc_info_t info;
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(long)pc);
|
||||
unw_get_proc_info(&cursor, &info);
|
||||
bases->tbase = info.extra;
|
||||
bases->dbase = 0; // dbase not used on Mac OS X
|
||||
bases->func = info.start_ip;
|
||||
DEBUG_PRINT_API("_Unwind_Find_FDE(pc=%p) => %p\n", pc, (void*)(long)info.unwind_info);
|
||||
return (void*)(long)info.unwind_info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context* context)
|
||||
{
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_word_t result;
|
||||
unw_get_reg(cursor, UNW_REG_SP, &result);
|
||||
DEBUG_PRINT_API("_Unwind_GetCFA(context=%p) => 0x%llX\n", context, (uint64_t)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get instruction pointer.
|
||||
// ipBefore is a boolean that says if IP is already adjusted to be the call
|
||||
// site address. Normally IP is the return address.
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context* context, int* ipBefore)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_GetIPInfo(context=%p)\n", context);
|
||||
*ipBefore = 0;
|
||||
return _Unwind_GetIP(context);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by programs with dynamic code generators that want
|
||||
// to register a dynamically generated FDE.
|
||||
// This function has existed on Mac OS X since 10.4, but
|
||||
// never worked before.
|
||||
//
|
||||
EXPORT void __register_frame(const void* fde)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame(%p)\n", fde);
|
||||
_unw_add_dynamic_fde((unw_word_t)(uintptr_t)fde);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by programs with dynamic code generators that want
|
||||
// to unregister a dynamically generated FDE.
|
||||
// This function has existed on Mac OS X since 10.4, but
|
||||
// never worked before.
|
||||
//
|
||||
EXPORT void __deregister_frame(const void* fde)
|
||||
{
|
||||
DEBUG_PRINT_API("__deregister_frame(%p)\n", fde);
|
||||
_unw_remove_dynamic_fde((unw_word_t)(uintptr_t)fde);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The following register/deregister functions are gcc extensions.
|
||||
// They have existed on Mac OS X, but have never worked because Mac OS X
|
||||
// before 10.6 used keymgr to track known FDEs, but these functions
|
||||
// never got updated to use keymgr.
|
||||
// For now, we implement these as do-nothing functions to keep any existing
|
||||
// applications working. We also add the not in 10.6 symbol so that nwe
|
||||
// application won't be able to use them.
|
||||
//
|
||||
|
||||
EXPORT void __register_frame_info_bases(const void* fde, void* ob, void* tb, void* db)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame_info_bases(%p,%p, %p, %p)\n", fde, ob, tb, db);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
}
|
||||
|
||||
EXPORT void __register_frame_info(const void* fde, void* ob)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame_info(%p, %p)\n", fde, ob);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
}
|
||||
|
||||
|
||||
EXPORT void __register_frame_info_table_bases(const void* fde, void* ob, void* tb, void* db)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame_info_table_bases(%p,%p, %p, %p)\n", fde, ob, tb, db);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
}
|
||||
|
||||
EXPORT void __register_frame_info_table(const void* fde, void* ob)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame_info_table(%p, %p)\n", fde, ob);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
}
|
||||
|
||||
EXPORT void __register_frame_table(const void* fde)
|
||||
{
|
||||
DEBUG_PRINT_API("__register_frame_table(%p)\n", fde);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
}
|
||||
|
||||
EXPORT void* __deregister_frame_info(const void* fde)
|
||||
{
|
||||
DEBUG_PRINT_API("__deregister_frame_info(%p)\n", fde);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT void* __deregister_frame_info_bases(const void* fde)
|
||||
{
|
||||
DEBUG_PRINT_API("__deregister_frame_info_bases(%p)\n", fde);
|
||||
// do nothing, this function never worked in Mac OS X
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions
|
||||
//
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
|
||||
|
||||
NOT_HERE_BEFORE_10_6(__register_frame)
|
||||
NOT_HERE_BEFORE_10_6(__deregister_frame)
|
||||
|
||||
|
||||
//
|
||||
// symbols in libSystem.dylib for compatibility, but we don't want any new code using them
|
||||
//
|
||||
NEVER_HERE(__register_frame_info_bases)
|
||||
NEVER_HERE(__register_frame_info)
|
||||
NEVER_HERE(__register_frame_info_table_bases)
|
||||
NEVER_HERE(__register_frame_info_table)
|
||||
NEVER_HERE(__register_frame_table)
|
||||
NEVER_HERE(__deregister_frame_info)
|
||||
NEVER_HERE(__deregister_frame_info_bases)
|
||||
|
||||
|
||||
#endif // __ppc__ || __i386__ || __x86_64__
|
||||
|
455
src/UnwindLevel1.c
Normal file
455
src/UnwindLevel1.c
Normal file
@ -0,0 +1,455 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2008-2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*
|
||||
* Implements C++ ABI Exception Handling Level 1 as documented at:
|
||||
* <http://www.codesourcery.com/cxx-abi/abi-eh.html>
|
||||
* using libunwind
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
#include "unwind.h"
|
||||
#include "InternalMacros.h"
|
||||
|
||||
#if __ppc__ || __i386__ || __x86_64__
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase1(unw_context_t* uc, struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
unw_cursor_t cursor1;
|
||||
unw_init_local(&cursor1, uc);
|
||||
|
||||
// walk each frame looking for a place to stop
|
||||
for (bool handlerNotFound = true; handlerNotFound; ) {
|
||||
|
||||
// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
|
||||
int stepResult = unw_step(&cursor1);
|
||||
if ( stepResult == 0 ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
else if ( stepResult < 0 ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
|
||||
// see if frame has code to run (has personality routine)
|
||||
unw_proc_info_t frameInfo;
|
||||
unw_word_t sp;
|
||||
if ( unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
|
||||
// debugging
|
||||
if ( DEBUG_PRINT_UNWINDING_TEST ) {
|
||||
char functionName[512];
|
||||
unw_word_t offset;
|
||||
if ( (unw_get_proc_name(&cursor1, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
|
||||
strcpy(functionName, ".anonymous.");
|
||||
unw_word_t pc;
|
||||
unw_get_reg(&cursor1, UNW_REG_IP, &pc);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n",
|
||||
exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
|
||||
}
|
||||
|
||||
// if there is a personality routine, ask it if it will want to stop at this frame
|
||||
if ( frameInfo.handler != 0 ) {
|
||||
__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): calling personality function %p\n", exception_object, p);
|
||||
_Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)(&cursor1));
|
||||
switch ( personalityResult ) {
|
||||
case _URC_HANDLER_FOUND:
|
||||
// found a catch clause or locals that need destructing in this frame
|
||||
// stop search and remember stack pointer at the frame
|
||||
handlerNotFound = false;
|
||||
unw_get_reg(&cursor1, UNW_REG_SP, &sp);
|
||||
exception_object->private_2 = sp;
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND\n", exception_object);
|
||||
return _URC_NO_REASON;
|
||||
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
// continue unwinding
|
||||
break;
|
||||
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase2(unw_context_t* uc, struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
unw_cursor_t cursor2;
|
||||
unw_init_local(&cursor2, uc);
|
||||
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
|
||||
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
while ( true ) {
|
||||
|
||||
// ask libuwind to get next frame (skip over first which is _Unwind_RaiseException)
|
||||
int stepResult = unw_step(&cursor2);
|
||||
if ( stepResult == 0 ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached bottom => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
else if ( stepResult < 0 ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
// get info about this frame
|
||||
unw_word_t sp;
|
||||
unw_proc_info_t frameInfo;
|
||||
unw_get_reg(&cursor2, UNW_REG_SP, &sp);
|
||||
if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info failed => _URC_FATAL_PHASE1_ERROR\n", exception_object);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
// debugging
|
||||
if ( DEBUG_PRINT_UNWINDING_TEST ) {
|
||||
char functionName[512];
|
||||
unw_word_t offset;
|
||||
if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
|
||||
strcpy(functionName, ".anonymous.");
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, lsda=0x%llX, personality=0x%llX\n",
|
||||
exception_object, frameInfo.start_ip, functionName, sp, frameInfo.lsda, frameInfo.handler);
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if ( frameInfo.handler != 0 ) {
|
||||
__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
|
||||
_Unwind_Action action = _UA_CLEANUP_PHASE;
|
||||
if ( sp == exception_object->private_2 )
|
||||
action = (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME); // tell personality this was the frame it marked in phase 1
|
||||
_Unwind_Reason_Code personalityResult = (*p)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)(&cursor2));
|
||||
switch ( personalityResult ) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
// continue unwinding
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
if ( sp == exception_object->private_2 ) {
|
||||
// phase 1 said we would stop at this frame, but we did not...
|
||||
ABORT("during phase1 personality function said it would stop here, but now if phase2 it did not stop here");
|
||||
}
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", exception_object);
|
||||
// personality routine says to transfer control to landing pad
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
if ( DEBUG_PRINT_UNWINDING_TEST ) {
|
||||
unw_word_t pc;
|
||||
unw_word_t sp;
|
||||
unw_get_reg(&cursor2, UNW_REG_IP, &pc);
|
||||
unw_get_reg(&cursor2, UNW_REG_SP, &sp);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering user code with ip=0x%llX, sp=0x%llX\n", exception_object, pc, sp);
|
||||
}
|
||||
unw_resume(&cursor2);
|
||||
// unw_resume() only returns if there was an error
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_MESSAGE("personality function returned unknown result %d", personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static _Unwind_Reason_Code unwind_phase2_forced(unw_context_t* uc, struct _Unwind_Exception* exception_object,
|
||||
_Unwind_Stop_Fn stop, void* stop_parameter)
|
||||
{
|
||||
unw_cursor_t cursor2;
|
||||
unw_init_local(&cursor2, uc);
|
||||
|
||||
// walk each frame until we reach where search phase said to stop
|
||||
while ( unw_step(&cursor2) > 0 ) {
|
||||
|
||||
// get info about this frame
|
||||
unw_proc_info_t frameInfo;
|
||||
if ( unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step failed => _URC_END_OF_STACK\n", exception_object);
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
}
|
||||
|
||||
// debugging
|
||||
if ( DEBUG_PRINT_UNWINDING_TEST ) {
|
||||
char functionName[512];
|
||||
unw_word_t offset;
|
||||
if ( (unw_get_proc_name(&cursor2, functionName, 512, &offset) != UNW_ESUCCESS) || (frameInfo.start_ip+offset > frameInfo.end_ip) )
|
||||
strcpy(functionName, ".anonymous.");
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): start_ip=0x%llX, func=%s, lsda=0x%llX, personality=0x%llX\n",
|
||||
exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler);
|
||||
}
|
||||
|
||||
// call stop function at each frame
|
||||
_Unwind_Action action = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE);
|
||||
_Unwind_Reason_Code stopResult = (*stop)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)(&cursor2), stop_parameter);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", exception_object, stopResult);
|
||||
if ( stopResult != _URC_NO_REASON ) {
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", exception_object);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
// if there is a personality routine, tell it we are unwinding
|
||||
if ( frameInfo.handler != 0 ) {
|
||||
__personality_routine p = (__personality_routine)(long)(frameInfo.handler);
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", exception_object, p);
|
||||
_Unwind_Reason_Code personalityResult = (*p)(1, action,
|
||||
exception_object->exception_class, exception_object,
|
||||
(struct _Unwind_Context*)(&cursor2));
|
||||
switch ( personalityResult ) {
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_CONTINUE_UNWIND\n", exception_object);
|
||||
// destructors called, continue unwinding
|
||||
break;
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned _URC_INSTALL_CONTEXT\n", exception_object);
|
||||
// we may get control back if landing pad calls _Unwind_Resume()
|
||||
unw_resume(&cursor2);
|
||||
break;
|
||||
default:
|
||||
// something went wrong
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): personality returned %d, _URC_FATAL_PHASE2_ERROR\n",
|
||||
exception_object, personalityResult);
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call stop function one last time and tell it we've reached the end of the stack
|
||||
DEBUG_PRINT_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop function with _UA_END_OF_STACK\n", exception_object);
|
||||
_Unwind_Action lastAction = (_Unwind_Action)(_UA_FORCE_UNWIND|_UA_CLEANUP_PHASE|_UA_END_OF_STACK);
|
||||
(*stop)(1, lastAction, exception_object->exception_class, exception_object, (struct _Unwind_Context*)(&cursor2), stop_parameter);
|
||||
|
||||
// clean up phase did not resume at the frame that the search phase said it would
|
||||
return _URC_FATAL_PHASE2_ERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by __cxa_throw. Only returns if there is a fatal error
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_RaiseException(ex_obj=%p)\n", exception_object);
|
||||
unw_context_t uc;
|
||||
unw_getcontext(&uc);
|
||||
|
||||
// mark that this is a non-forced unwind, so _Unwind_Resume() can do the right thing
|
||||
exception_object->private_1 = 0;
|
||||
exception_object->private_2 = 0;
|
||||
|
||||
// phase 1: the search phase
|
||||
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
|
||||
if ( phase1 != _URC_NO_REASON )
|
||||
return phase1;
|
||||
|
||||
// phase 2: the clean up phase
|
||||
return unwind_phase2(&uc, exception_object);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// When _Unwind_RaiseException() is in phase2, it hands control
|
||||
// to the personality function at each frame. The personality
|
||||
// may force a jump to a landing pad in that function, the landing
|
||||
// pad code may then call _Unwind_Resume() to continue with the
|
||||
// unwinding. Note: the call to _Unwind_Resume() is from compiler
|
||||
// geneated user code. All other _Unwind_* routines are called
|
||||
// by the C++ runtime __cxa_* routines.
|
||||
//
|
||||
// Re-throwing an exception is implemented by having the code call
|
||||
// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
|
||||
//
|
||||
EXPORT void _Unwind_Resume(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
|
||||
unw_context_t uc;
|
||||
unw_getcontext(&uc);
|
||||
|
||||
if ( exception_object->private_1 != 0 )
|
||||
unwind_phase2_forced(&uc, exception_object, (_Unwind_Stop_Fn)exception_object->private_1, (void*)exception_object->private_2);
|
||||
else
|
||||
unwind_phase2(&uc, exception_object);
|
||||
|
||||
// clients assume _Unwind_Resume() does not return, so all we can do is abort.
|
||||
ABORT("_Unwind_Resume() can't return");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Not used by C++.
|
||||
// Unwinds stack, calling "stop" function at each frame
|
||||
// Could be used to implement longjmp().
|
||||
//
|
||||
EXPORT _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception* exception_object, _Unwind_Stop_Fn stop, void* stop_parameter)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", exception_object, stop);
|
||||
unw_context_t uc;
|
||||
unw_getcontext(&uc);
|
||||
|
||||
// mark that this is a forced unwind, so _Unwind_Resume() can do the right thing
|
||||
exception_object->private_1 = (uintptr_t)stop;
|
||||
exception_object->private_2 = (uintptr_t)stop_parameter;
|
||||
|
||||
// doit
|
||||
return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get LSDA for current frame
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context* context)
|
||||
{
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_proc_info_t frameInfo;
|
||||
uintptr_t result = 0;
|
||||
if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS )
|
||||
result = frameInfo.lsda;
|
||||
DEBUG_PRINT_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lX\n", context, result);
|
||||
if ( result != 0 ) {
|
||||
if ( *((uint8_t*)result) != 0xFF )
|
||||
DEBUG_MESSAGE("lsda at 0x%lX does not start with 0xFF\n", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get register values
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context* context, int index)
|
||||
{
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_word_t result;
|
||||
unw_get_reg(cursor, index, &result);
|
||||
DEBUG_PRINT_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n", context, index, (uint64_t)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to alter register values
|
||||
//
|
||||
EXPORT void _Unwind_SetGR(struct _Unwind_Context* context, int index, uintptr_t new_value)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0llX)\n", context, index, (uint64_t)new_value);
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_set_reg(cursor, index, new_value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to get instruction pointer
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context* context)
|
||||
{
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_word_t result;
|
||||
unw_get_reg(cursor, UNW_REG_IP, &result);
|
||||
DEBUG_PRINT_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context, (uint64_t)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to alter instruction pointer
|
||||
//
|
||||
EXPORT void _Unwind_SetIP(struct _Unwind_Context* context, uintptr_t new_value)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n", context, (uint64_t)new_value);
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_set_reg(cursor, UNW_REG_IP, new_value);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 to find the start of the function
|
||||
//
|
||||
EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context* context)
|
||||
{
|
||||
unw_cursor_t* cursor = (unw_cursor_t*)context;
|
||||
unw_proc_info_t frameInfo;
|
||||
uintptr_t result = 0;
|
||||
if ( unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS )
|
||||
result = frameInfo.start_ip;
|
||||
DEBUG_PRINT_API("_Unwind_GetRegionStart(context=%p) => 0x%lX\n", context, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Called by personality handler during phase 2 if a foreign exception is caught
|
||||
//
|
||||
EXPORT void _Unwind_DeleteException(struct _Unwind_Exception* exception_object)
|
||||
{
|
||||
DEBUG_PRINT_API("_Unwind_DeleteException(ex_obj=%p)\n", exception_object);
|
||||
if ( exception_object->exception_cleanup != NULL )
|
||||
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exception_object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in earlier versions
|
||||
//
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_Resume)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
|
||||
NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
|
||||
|
||||
#endif // __ppc__ || __i386__ || __x86_64__
|
255
src/dwarf2.h
Normal file
255
src/dwarf2.h
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2008 Apple, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
/* These constants were taken from version 3 of the DWARF standard,
|
||||
which is Copyright (c) 2005 Free Standards Group, and
|
||||
Copyright (c) 1992, 1993 UNIX International, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __DWARF2__
|
||||
#define __DWARF2__
|
||||
|
||||
// dwarf unwind instructions
|
||||
enum {
|
||||
DW_CFA_nop = 0x0,
|
||||
DW_CFA_set_loc = 0x1,
|
||||
DW_CFA_advance_loc1 = 0x2,
|
||||
DW_CFA_advance_loc2 = 0x3,
|
||||
DW_CFA_advance_loc4 = 0x4,
|
||||
DW_CFA_offset_extended = 0x5,
|
||||
DW_CFA_restore_extended = 0x6,
|
||||
DW_CFA_undefined = 0x7,
|
||||
DW_CFA_same_value = 0x8,
|
||||
DW_CFA_register = 0x9,
|
||||
DW_CFA_remember_state = 0xA,
|
||||
DW_CFA_restore_state = 0xB,
|
||||
DW_CFA_def_cfa = 0xC,
|
||||
DW_CFA_def_cfa_register = 0xD,
|
||||
DW_CFA_def_cfa_offset = 0xE,
|
||||
DW_CFA_def_cfa_expression = 0xF,
|
||||
DW_CFA_expression = 0x10,
|
||||
DW_CFA_offset_extended_sf = 0x11,
|
||||
DW_CFA_def_cfa_sf = 0x12,
|
||||
DW_CFA_def_cfa_offset_sf = 0x13,
|
||||
DW_CFA_val_offset = 0x14,
|
||||
DW_CFA_val_offset_sf = 0x15,
|
||||
DW_CFA_val_expression = 0x16,
|
||||
DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
|
||||
DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register
|
||||
DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
|
||||
|
||||
// GNU extensions
|
||||
DW_CFA_GNU_window_save = 0x2D,
|
||||
DW_CFA_GNU_args_size = 0x2E,
|
||||
DW_CFA_GNU_negative_offset_extended = 0x2F
|
||||
};
|
||||
|
||||
|
||||
// FSF exception handling Pointer-Encoding constants
|
||||
// Used in CFI augmentation by gcc compiler
|
||||
enum {
|
||||
DW_EH_PE_ptr = 0x00,
|
||||
DW_EH_PE_uleb128 = 0x01,
|
||||
DW_EH_PE_udata2 = 0x02,
|
||||
DW_EH_PE_udata4 = 0x03,
|
||||
DW_EH_PE_udata8 = 0x04,
|
||||
DW_EH_PE_signed = 0x08,
|
||||
DW_EH_PE_sleb128 = 0x09,
|
||||
DW_EH_PE_sdata2 = 0x0A,
|
||||
DW_EH_PE_sdata4 = 0x0B,
|
||||
DW_EH_PE_sdata8 = 0x0C,
|
||||
DW_EH_PE_absptr = 0x00,
|
||||
DW_EH_PE_pcrel = 0x10,
|
||||
DW_EH_PE_textrel = 0x20,
|
||||
DW_EH_PE_datarel = 0x30,
|
||||
DW_EH_PE_funcrel = 0x40,
|
||||
DW_EH_PE_aligned = 0x50,
|
||||
DW_EH_PE_indirect = 0x80,
|
||||
DW_EH_PE_omit = 0xFF
|
||||
};
|
||||
|
||||
|
||||
// DWARF expressions
|
||||
enum {
|
||||
DW_OP_addr = 0x03, // constant address (size target specific)
|
||||
DW_OP_deref = 0x06,
|
||||
DW_OP_const1u = 0x08, // 1-byte constant
|
||||
DW_OP_const1s = 0x09, // 1-byte constant
|
||||
DW_OP_const2u = 0x0A, // 2-byte constant
|
||||
DW_OP_const2s = 0x0B, // 2-byte constant
|
||||
DW_OP_const4u = 0x0C, // 4-byte constant
|
||||
DW_OP_const4s = 0x0D, // 4-byte constant
|
||||
DW_OP_const8u = 0x0E, // 8-byte constant
|
||||
DW_OP_const8s = 0x0F, // 8-byte constant
|
||||
DW_OP_constu = 0x10, // ULEB128 constant
|
||||
DW_OP_consts = 0x11, // SLEB128 constant
|
||||
DW_OP_dup = 0x12,
|
||||
DW_OP_drop = 0x13,
|
||||
DW_OP_over = 0x14,
|
||||
DW_OP_pick = 0x15, // 1-byte stack index
|
||||
DW_OP_swap = 0x16,
|
||||
DW_OP_rot = 0x17,
|
||||
DW_OP_xderef = 0x18,
|
||||
DW_OP_abs = 0x19,
|
||||
DW_OP_and = 0x1A,
|
||||
DW_OP_div = 0x1B,
|
||||
DW_OP_minus = 0x1C,
|
||||
DW_OP_mod = 0x1D,
|
||||
DW_OP_mul = 0x1E,
|
||||
DW_OP_neg = 0x1F,
|
||||
DW_OP_not = 0x20,
|
||||
DW_OP_or = 0x21,
|
||||
DW_OP_plus = 0x22,
|
||||
DW_OP_plus_uconst = 0x23, // ULEB128 addend
|
||||
DW_OP_shl = 0x24,
|
||||
DW_OP_shr = 0x25,
|
||||
DW_OP_shra = 0x26,
|
||||
DW_OP_xor = 0x27,
|
||||
DW_OP_skip = 0x2F, // signed 2-byte constant
|
||||
DW_OP_bra = 0x28, // signed 2-byte constant
|
||||
DW_OP_eq = 0x29,
|
||||
DW_OP_ge = 0x2A,
|
||||
DW_OP_gt = 0x2B,
|
||||
DW_OP_le = 0x2C,
|
||||
DW_OP_lt = 0x2D,
|
||||
DW_OP_ne = 0x2E,
|
||||
DW_OP_lit0 = 0x30, // Literal 0
|
||||
DW_OP_lit1 = 0x31, // Literal 1
|
||||
DW_OP_lit2 = 0x32, // Literal 2
|
||||
DW_OP_lit3 = 0x33, // Literal 3
|
||||
DW_OP_lit4 = 0x34, // Literal 4
|
||||
DW_OP_lit5 = 0x35, // Literal 5
|
||||
DW_OP_lit6 = 0x36, // Literal 6
|
||||
DW_OP_lit7 = 0x37, // Literal 7
|
||||
DW_OP_lit8 = 0x38, // Literal 8
|
||||
DW_OP_lit9 = 0x39, // Literal 9
|
||||
DW_OP_lit10 = 0x3A, // Literal 10
|
||||
DW_OP_lit11 = 0x3B, // Literal 11
|
||||
DW_OP_lit12 = 0x3C, // Literal 12
|
||||
DW_OP_lit13 = 0x3D, // Literal 13
|
||||
DW_OP_lit14 = 0x3E, // Literal 14
|
||||
DW_OP_lit15 = 0x3F, // Literal 15
|
||||
DW_OP_lit16 = 0x40, // Literal 16
|
||||
DW_OP_lit17 = 0x41, // Literal 17
|
||||
DW_OP_lit18 = 0x42, // Literal 18
|
||||
DW_OP_lit19 = 0x43, // Literal 19
|
||||
DW_OP_lit20 = 0x44, // Literal 20
|
||||
DW_OP_lit21 = 0x45, // Literal 21
|
||||
DW_OP_lit22 = 0x46, // Literal 22
|
||||
DW_OP_lit23 = 0x47, // Literal 23
|
||||
DW_OP_lit24 = 0x48, // Literal 24
|
||||
DW_OP_lit25 = 0x49, // Literal 25
|
||||
DW_OP_lit26 = 0x4A, // Literal 26
|
||||
DW_OP_lit27 = 0x4B, // Literal 27
|
||||
DW_OP_lit28 = 0x4C, // Literal 28
|
||||
DW_OP_lit29 = 0x4D, // Literal 29
|
||||
DW_OP_lit30 = 0x4E, // Literal 30
|
||||
DW_OP_lit31 = 0x4F, // Literal 31
|
||||
DW_OP_reg0 = 0x50, // Contents of reg0
|
||||
DW_OP_reg1 = 0x51, // Contents of reg1
|
||||
DW_OP_reg2 = 0x52, // Contents of reg2
|
||||
DW_OP_reg3 = 0x53, // Contents of reg3
|
||||
DW_OP_reg4 = 0x54, // Contents of reg4
|
||||
DW_OP_reg5 = 0x55, // Contents of reg5
|
||||
DW_OP_reg6 = 0x56, // Contents of reg6
|
||||
DW_OP_reg7 = 0x57, // Contents of reg7
|
||||
DW_OP_reg8 = 0x58, // Contents of reg8
|
||||
DW_OP_reg9 = 0x59, // Contents of reg9
|
||||
DW_OP_reg10 = 0x5A, // Contents of reg10
|
||||
DW_OP_reg11 = 0x5B, // Contents of reg11
|
||||
DW_OP_reg12 = 0x5C, // Contents of reg12
|
||||
DW_OP_reg13 = 0x5D, // Contents of reg13
|
||||
DW_OP_reg14 = 0x5E, // Contents of reg14
|
||||
DW_OP_reg15 = 0x5F, // Contents of reg15
|
||||
DW_OP_reg16 = 0x60, // Contents of reg16
|
||||
DW_OP_reg17 = 0x61, // Contents of reg17
|
||||
DW_OP_reg18 = 0x62, // Contents of reg18
|
||||
DW_OP_reg19 = 0x63, // Contents of reg19
|
||||
DW_OP_reg20 = 0x64, // Contents of reg20
|
||||
DW_OP_reg21 = 0x65, // Contents of reg21
|
||||
DW_OP_reg22 = 0x66, // Contents of reg22
|
||||
DW_OP_reg23 = 0x67, // Contents of reg23
|
||||
DW_OP_reg24 = 0x68, // Contents of reg24
|
||||
DW_OP_reg25 = 0x69, // Contents of reg25
|
||||
DW_OP_reg26 = 0x6A, // Contents of reg26
|
||||
DW_OP_reg27 = 0x6B, // Contents of reg27
|
||||
DW_OP_reg28 = 0x6C, // Contents of reg28
|
||||
DW_OP_reg29 = 0x6D, // Contents of reg29
|
||||
DW_OP_reg30 = 0x6E, // Contents of reg30
|
||||
DW_OP_reg31 = 0x6F, // Contents of reg31
|
||||
DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset
|
||||
DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset
|
||||
DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset
|
||||
DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset
|
||||
DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset
|
||||
DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset
|
||||
DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset
|
||||
DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset
|
||||
DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset
|
||||
DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset
|
||||
DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset
|
||||
DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset
|
||||
DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset
|
||||
DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset
|
||||
DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset
|
||||
DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset
|
||||
DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset
|
||||
DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset
|
||||
DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset
|
||||
DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset
|
||||
DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset
|
||||
DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset
|
||||
DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset
|
||||
DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset
|
||||
DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset
|
||||
DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset
|
||||
DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset
|
||||
DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset
|
||||
DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset
|
||||
DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset
|
||||
DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset
|
||||
DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset
|
||||
DW_OP_regx = 0x90, // ULEB128 register
|
||||
DW_OP_fbreg = 0x91, // SLEB128 offset
|
||||
DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset
|
||||
DW_OP_piece = 0x93, // ULEB128 size of piece addressed
|
||||
DW_OP_deref_size = 0x94, // 1-byte size of data retrieved
|
||||
DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved
|
||||
DW_OP_nop = 0x96,
|
||||
DW_OP_push_object_addres = 0x97,
|
||||
DW_OP_call2 = 0x98, // 2-byte offset of DIE
|
||||
DW_OP_call4 = 0x99, // 4-byte offset of DIE
|
||||
DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE
|
||||
DW_OP_lo_user = 0xE0,
|
||||
DW_OP_APPLE_uninit = 0xF0,
|
||||
DW_OP_hi_user = 0xFF
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
49
src/libunwind_priv.h
Normal file
49
src/libunwind_priv.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; -*-
|
||||
*
|
||||
* Copyright (c) 2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LIBUNWIND_PRIV__
|
||||
#define __LIBUNWIND_PRIV__
|
||||
|
||||
#include <libunwind.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// SPI
|
||||
extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
|
||||
|
||||
// IPI
|
||||
extern void _unw_add_dynamic_fde(unw_word_t fde);
|
||||
extern void _unw_remove_dynamic_fde(unw_word_t fde);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
380
src/libuwind.cxx
Normal file
380
src/libuwind.cxx
Normal file
@ -0,0 +1,380 @@
|
||||
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||
*
|
||||
* Copyright (c) 2007-2008 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/machine.h>
|
||||
#include <new>
|
||||
|
||||
#include "libunwind.h"
|
||||
#include "libunwind_priv.h"
|
||||
|
||||
#include "UnwindCursor.hpp"
|
||||
|
||||
|
||||
|
||||
using namespace libunwind;
|
||||
|
||||
|
||||
// setup debug logging hooks
|
||||
INITIALIZE_DEBUG_PRINT_API
|
||||
INITIALIZE_DEBUG_PRINT_UNWINDING
|
||||
|
||||
|
||||
#if __ppc__ || __i386__ || __x86_64__
|
||||
|
||||
// internal object to represent this processes address space
|
||||
static LocalAddressSpace sThisAddressSpace;
|
||||
|
||||
///
|
||||
/// record the registers and stack position of the caller
|
||||
///
|
||||
extern int unw_getcontext(unw_context_t*);
|
||||
// note: unw_getcontext() implemented in assembly
|
||||
|
||||
|
||||
///
|
||||
/// create a cursor of a thread in this process given 'context' recorded by unw_getcontext()
|
||||
///
|
||||
EXPORT int unw_init_local(unw_cursor_t* cursor, unw_context_t* context)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_init_local(cursor=%p, context=%p)\n", cursor, context);
|
||||
// use "placement new" to allocate UnwindCursor in the cursor buffer
|
||||
#if __i386__
|
||||
new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86>(context, sThisAddressSpace);
|
||||
#elif __x86_64__
|
||||
new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_x86_64>(context, sThisAddressSpace);
|
||||
#elif __ppc__
|
||||
new ((void*)cursor) UnwindCursor<LocalAddressSpace,Registers_ppc>(context, sThisAddressSpace);
|
||||
#endif
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
co->setInfoBasedOnIPRegister();
|
||||
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
|
||||
#if UNW_REMOTE
|
||||
|
||||
EXPORT unw_addr_space_t unw_local_addr_space = (unw_addr_space_t)&sThisAddressSpace;
|
||||
|
||||
///
|
||||
/// create a cursor into a thread in another process
|
||||
///
|
||||
EXPORT int unw_init_remote_thread(unw_cursor_t* cursor, unw_addr_space_t as, thread_t thread)
|
||||
{
|
||||
// special case: unw_init_remote(xx, unw_local_addr_space, xx)
|
||||
if ( as == (unw_addr_space_t)&sThisAddressSpace )
|
||||
return unw_init_local(cursor, NULL); //FIXME
|
||||
|
||||
// use "placement new" to allocate UnwindCursor in the cursor buffer
|
||||
switch ( as->cpuType ) {
|
||||
case CPU_TYPE_I386:
|
||||
new ((void*)cursor) UnwindCursor<OtherAddressSpace<Pointer32<LittleEndian> >,
|
||||
Registers_x86>(((unw_addr_space_i386*)as)->oas, thread);
|
||||
break;
|
||||
case CPU_TYPE_X86_64:
|
||||
new ((void*)cursor) UnwindCursor<OtherAddressSpace<Pointer64<LittleEndian> >,
|
||||
Registers_x86_64>(((unw_addr_space_x86_64*)as)->oas, thread);
|
||||
break;
|
||||
case CPU_TYPE_POWERPC:
|
||||
new ((void*)cursor) UnwindCursor<OtherAddressSpace<Pointer32<BigEndian> >,
|
||||
Registers_ppc>(((unw_addr_space_ppc*)as)->oas, thread);
|
||||
break;
|
||||
default:
|
||||
return UNW_EUNSPEC;
|
||||
}
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
|
||||
static bool rosetta(task_t task)
|
||||
{
|
||||
return false; // FIXME
|
||||
}
|
||||
|
||||
static bool is64bit(task_t task)
|
||||
{
|
||||
return false; // FIXME
|
||||
}
|
||||
|
||||
///
|
||||
/// create an address_space object for use in examining another task
|
||||
///
|
||||
EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task)
|
||||
{
|
||||
#if __i386__
|
||||
if ( rosetta(task) ) {
|
||||
unw_addr_space_ppc* as = new unw_addr_space_ppc(task);
|
||||
as->taskPort = task;
|
||||
as->cpuType = CPU_TYPE_POWERPC;
|
||||
//as->oas
|
||||
}
|
||||
else if ( is64bit(task) ) {
|
||||
unw_addr_space_x86_64* as = new unw_addr_space_x86_64(task);
|
||||
as->taskPort = task;
|
||||
as->cpuType = CPU_TYPE_X86_64;
|
||||
//as->oas
|
||||
}
|
||||
else {
|
||||
unw_addr_space_i386* as = new unw_addr_space_i386(task);
|
||||
as->taskPort = task;
|
||||
as->cpuType = CPU_TYPE_I386;
|
||||
//as->oas
|
||||
}
|
||||
#else
|
||||
// FIXME
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// delete an address_space object
|
||||
///
|
||||
EXPORT void unw_destroy_addr_space(unw_addr_space_t asp)
|
||||
{
|
||||
switch ( asp->cpuType ) {
|
||||
#if __i386__ || __x86_64__
|
||||
case CPU_TYPE_I386:
|
||||
{
|
||||
unw_addr_space_i386* as = (unw_addr_space_i386*)asp;
|
||||
delete as;
|
||||
}
|
||||
break;
|
||||
case CPU_TYPE_X86_64:
|
||||
{
|
||||
unw_addr_space_x86_64* as = (unw_addr_space_x86_64*)asp;
|
||||
delete as;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case CPU_TYPE_POWERPC:
|
||||
{
|
||||
unw_addr_space_ppc* as = (unw_addr_space_ppc*)asp;
|
||||
delete as;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // UNW_REMOTE
|
||||
|
||||
|
||||
///
|
||||
/// get value of specified register at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_get_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t* value)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
if ( co->validReg(regNum) ) {
|
||||
*value = co->getReg(regNum);
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
return UNW_EBADREG;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// set value of specified register at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_set_reg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_word_t value)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)\n", cursor, regNum, value);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
if ( co->validReg(regNum) ) {
|
||||
co->setReg(regNum, value);
|
||||
// specical case altering IP to re-find info (being called by personality function)
|
||||
if ( regNum == UNW_REG_IP ) {
|
||||
unw_proc_info_t info;
|
||||
co->getInfo(&info);
|
||||
uint64_t orgArgSize = info.gp;
|
||||
uint64_t orgFuncStart = info.start_ip;
|
||||
co->setInfoBasedOnIPRegister(false);
|
||||
// and adjust REG_SP if there was a DW_CFA_GNU_args_size
|
||||
if ( (orgFuncStart == info.start_ip) && (orgArgSize != 0) )
|
||||
co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + orgArgSize);
|
||||
}
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
return UNW_EBADREG;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// get value of specified float register at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_get_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t* value)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)\n", cursor, regNum, value);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
if ( co->validFloatReg(regNum) ) {
|
||||
*value = co->getFloatReg(regNum);
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
return UNW_EBADREG;
|
||||
}
|
||||
|
||||
///
|
||||
/// set value of specified float register at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_set_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum, unw_fpreg_t value)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)\n", cursor, regNum, value);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
if ( co->validFloatReg(regNum) ) {
|
||||
co->setFloatReg(regNum, value);
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
return UNW_EBADREG;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// move cursor to next frame
|
||||
///
|
||||
EXPORT int unw_step(unw_cursor_t* cursor)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_step(cursor=%p)\n", cursor);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
return co->step();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// get unwind info at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_get_proc_info(unw_cursor_t* cursor, unw_proc_info_t* info)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_get_proc_info(cursor=%p, &info=%p)\n", cursor, info);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
co->getInfo(info);
|
||||
if ( info->end_ip == 0 )
|
||||
return UNW_ENOINFO;
|
||||
else
|
||||
return UNW_ESUCCESS;
|
||||
}
|
||||
|
||||
///
|
||||
/// resume execution at cursor position (aka longjump)
|
||||
///
|
||||
EXPORT int unw_resume(unw_cursor_t* cursor)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_resume(cursor=%p)\n", cursor);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
co->jumpto();
|
||||
return UNW_EUNSPEC;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// get name of function at cursor position in stack frame
|
||||
///
|
||||
EXPORT int unw_get_proc_name(unw_cursor_t* cursor, char* buf, size_t bufLen, unw_word_t* offset)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%ld)\n", cursor, buf, bufLen);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
if ( co->getFunctionName(buf, bufLen, offset) )
|
||||
return UNW_ESUCCESS;
|
||||
else
|
||||
return UNW_EUNSPEC;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// checks if a register is a floating-point register
|
||||
///
|
||||
EXPORT int unw_is_fpreg(unw_cursor_t* cursor, unw_regnum_t regNum)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_is_fpreg(cursor=%p, regNum=%d)\n", cursor, regNum);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
return co->validFloatReg(regNum);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// checks if a register is a floating-point register
|
||||
///
|
||||
EXPORT const char* unw_regname(unw_cursor_t* cursor, unw_regnum_t regNum)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_regname(cursor=%p, regNum=%d)\n", cursor, regNum);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
return co->getRegisterName(regNum);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// checks if current frame is signal trampoline
|
||||
///
|
||||
EXPORT int unw_is_signal_frame(unw_cursor_t* cursor)
|
||||
{
|
||||
DEBUG_PRINT_API("unw_is_signal_frame(cursor=%p)\n", cursor);
|
||||
AbstractUnwindCursor* co = (AbstractUnwindCursor*)cursor;
|
||||
return co->isSignalFrame();
|
||||
}
|
||||
|
||||
#if !FOR_DYLD
|
||||
///
|
||||
/// SPI: walks cached dwarf entries
|
||||
///
|
||||
EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh))
|
||||
{
|
||||
DEBUG_PRINT_API("unw_iterate_dwarf_unwind_cache(func=%p)\n", func);
|
||||
DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
|
||||
}
|
||||
#endif // !FOR_DYLD
|
||||
|
||||
|
||||
#if !FOR_DYLD
|
||||
//
|
||||
// IPI: for __register_frame()
|
||||
//
|
||||
void _unw_add_dynamic_fde(unw_word_t fde)
|
||||
{
|
||||
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
|
||||
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
|
||||
const char* message = CFI_Parser<LocalAddressSpace>::decodeFDE(sThisAddressSpace, (LocalAddressSpace::pint_t)fde, & fdeInfo, &cieInfo);
|
||||
if ( message == NULL ) {
|
||||
// dynamically registered FDEs don't have a mach_header group they are in. Use fde as mh_group
|
||||
unw_word_t mh_group = fdeInfo.fdeStart;
|
||||
DwarfFDECache<LocalAddressSpace>::add(mh_group, fdeInfo.pcStart, fdeInfo.pcEnd, fdeInfo.fdeStart);
|
||||
}
|
||||
else {
|
||||
DEBUG_MESSAGE("_unw_add_dynamic_fde: bad fde: %s", message);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// IPI: for __deregister_frame()
|
||||
//
|
||||
void _unw_remove_dynamic_fde(unw_word_t fde)
|
||||
{
|
||||
// fde is own mh_group
|
||||
DwarfFDECache<LocalAddressSpace>::removeAllIn(fde);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __ppc__ || __i386__ || __x86_64__
|
||||
|
||||
|
||||
|
||||
|
229
src/unw_getcontext.S
Normal file
229
src/unw_getcontext.S
Normal file
@ -0,0 +1,229 @@
|
||||
|
||||
#if __i386__ || __x86_64__ || __ppc__
|
||||
|
||||
.text
|
||||
.globl _unw_getcontext
|
||||
_unw_getcontext:
|
||||
|
||||
#endif // __i386__ || __x86_64__ || __ppc__
|
||||
|
||||
|
||||
#if __i386__
|
||||
|
||||
#
|
||||
# extern int unw_getcontext(unw_context_t* thread_state)
|
||||
#
|
||||
# On entry:
|
||||
# + +
|
||||
# +-----------------------+
|
||||
# + thread_state pointer +
|
||||
# +-----------------------+
|
||||
# + return address +
|
||||
# +-----------------------+ <-- SP
|
||||
# + +
|
||||
#
|
||||
push %eax
|
||||
movl 8(%esp), %eax
|
||||
movl %ebx, 4(%eax)
|
||||
movl %ecx, 8(%eax)
|
||||
movl %edx, 12(%eax)
|
||||
movl %edi, 16(%eax)
|
||||
movl %esi, 20(%eax)
|
||||
movl %ebp, 24(%eax)
|
||||
movl %esp, %edx
|
||||
addl $8, %edx
|
||||
movl %edx, 28(%eax) # store what sp was at call site as esp
|
||||
# skip ss
|
||||
# skip eflags
|
||||
movl 4(%esp), %edx
|
||||
movl %edx, 40(%eax) # store return address as eip
|
||||
# skip cs
|
||||
# skip ds
|
||||
# skip es
|
||||
# skip fs
|
||||
# skip gs
|
||||
movl (%esp), %edx
|
||||
movl %edx, (%eax) # store original eax
|
||||
popl %eax
|
||||
xorl %eax, %eax # return UNW_ESUCCESS
|
||||
ret
|
||||
|
||||
#elif __x86_64__
|
||||
|
||||
#
|
||||
# extern int unw_getcontext(unw_context_t* thread_state)
|
||||
#
|
||||
# On entry:
|
||||
# thread_state pointer is in rdi
|
||||
#
|
||||
movq %rax, (%rdi)
|
||||
movq %rbx, 8(%rdi)
|
||||
movq %rcx, 16(%rdi)
|
||||
movq %rdx, 24(%rdi)
|
||||
movq %rdi, 32(%rdi)
|
||||
movq %rsi, 40(%rdi)
|
||||
movq %rbp, 48(%rdi)
|
||||
movq %rsp, 56(%rdi)
|
||||
addq $8, 56(%rdi)
|
||||
movq %r8, 64(%rdi)
|
||||
movq %r9, 72(%rdi)
|
||||
movq %r10, 80(%rdi)
|
||||
movq %r11, 88(%rdi)
|
||||
movq %r12, 96(%rdi)
|
||||
movq %r13,104(%rdi)
|
||||
movq %r14,112(%rdi)
|
||||
movq %r15,120(%rdi)
|
||||
movq (%rsp),%rsi
|
||||
movq %rsi,128(%rdi) # store return address as rip
|
||||
# skip rflags
|
||||
# skip cs
|
||||
# skip fs
|
||||
# skip gs
|
||||
xorl %eax, %eax # return UNW_ESUCCESS
|
||||
ret
|
||||
|
||||
#elif __ppc__
|
||||
|
||||
;
|
||||
; extern int unw_getcontext(unw_context_t* thread_state)
|
||||
;
|
||||
; On entry:
|
||||
; thread_state pointer is in r3
|
||||
;
|
||||
stw r0, 8(r3)
|
||||
mflr r0
|
||||
stw r0, 0(r3) ; store lr as ssr0
|
||||
stw r1, 12(r3)
|
||||
stw r2, 16(r3)
|
||||
stw r3, 20(r3)
|
||||
stw r4, 24(r3)
|
||||
stw r5, 28(r3)
|
||||
stw r6, 32(r3)
|
||||
stw r7, 36(r3)
|
||||
stw r8, 40(r3)
|
||||
stw r9, 44(r3)
|
||||
stw r10, 48(r3)
|
||||
stw r11, 52(r3)
|
||||
stw r12, 56(r3)
|
||||
stw r13, 60(r3)
|
||||
stw r14, 64(r3)
|
||||
stw r15, 68(r3)
|
||||
stw r16, 72(r3)
|
||||
stw r17, 76(r3)
|
||||
stw r18, 80(r3)
|
||||
stw r19, 84(r3)
|
||||
stw r20, 88(r3)
|
||||
stw r21, 92(r3)
|
||||
stw r22, 96(r3)
|
||||
stw r23,100(r3)
|
||||
stw r24,104(r3)
|
||||
stw r25,108(r3)
|
||||
stw r26,112(r3)
|
||||
stw r27,116(r3)
|
||||
stw r28,120(r3)
|
||||
stw r29,124(r3)
|
||||
stw r30,128(r3)
|
||||
stw r31,132(r3)
|
||||
|
||||
; save VRSave register
|
||||
mfspr r0,256
|
||||
stw r0,156(r3)
|
||||
; save CR registers
|
||||
mfcr r0
|
||||
stw r0,136(r3)
|
||||
; save CTR register
|
||||
mfctr r0
|
||||
stw r0,148(r3)
|
||||
|
||||
; save float registers
|
||||
stfd f0, 160(r3)
|
||||
stfd f1, 168(r3)
|
||||
stfd f2, 176(r3)
|
||||
stfd f3, 184(r3)
|
||||
stfd f4, 192(r3)
|
||||
stfd f5, 200(r3)
|
||||
stfd f6, 208(r3)
|
||||
stfd f7, 216(r3)
|
||||
stfd f8, 224(r3)
|
||||
stfd f9, 232(r3)
|
||||
stfd f10,240(r3)
|
||||
stfd f11,248(r3)
|
||||
stfd f12,256(r3)
|
||||
stfd f13,264(r3)
|
||||
stfd f14,272(r3)
|
||||
stfd f15,280(r3)
|
||||
stfd f16,288(r3)
|
||||
stfd f17,296(r3)
|
||||
stfd f18,304(r3)
|
||||
stfd f19,312(r3)
|
||||
stfd f20,320(r3)
|
||||
stfd f21,328(r3)
|
||||
stfd f22,336(r3)
|
||||
stfd f23,344(r3)
|
||||
stfd f24,352(r3)
|
||||
stfd f25,360(r3)
|
||||
stfd f26,368(r3)
|
||||
stfd f27,376(r3)
|
||||
stfd f28,384(r3)
|
||||
stfd f29,392(r3)
|
||||
stfd f30,400(r3)
|
||||
stfd f31,408(r3)
|
||||
|
||||
|
||||
; save vector registers
|
||||
|
||||
subi r4,r1,16
|
||||
rlwinm r4,r4,0,0,27 ; mask low 4-bits
|
||||
; r4 is now a 16-byte aligned pointer into the red zone
|
||||
|
||||
#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
|
||||
stvx _vec,0,r4 @\
|
||||
lwz r5, 0(r4) @\
|
||||
stw r5, _offset(r3) @\
|
||||
lwz r5, 4(r4) @\
|
||||
stw r5, _offset+4(r3) @\
|
||||
lwz r5, 8(r4) @\
|
||||
stw r5, _offset+8(r3) @\
|
||||
lwz r5, 12(r4) @\
|
||||
stw r5, _offset+12(r3)
|
||||
|
||||
SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
|
||||
SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
|
||||
SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
|
||||
SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
|
||||
SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
|
||||
SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
|
||||
SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
|
||||
SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
|
||||
SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
|
||||
SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
|
||||
SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
|
||||
SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
|
||||
SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
|
||||
SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
|
||||
SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
|
||||
SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
|
||||
SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
|
||||
SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
|
||||
SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
|
||||
SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
|
||||
SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
|
||||
SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
|
||||
SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
|
||||
SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
|
||||
SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
|
||||
SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
|
||||
SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
|
||||
SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
|
||||
SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
|
||||
SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
|
||||
SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
|
||||
SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
|
||||
|
||||
li r3, 0 ; return UNW_ESUCCESS
|
||||
blr
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
59
testsuite/Unwind_Backtrace.c
Normal file
59
testsuite/Unwind_Backtrace.c
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions -fomit-frame-pointer
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64 -fomit-frame-pointer
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: backtrace2.c -arch ppc -fexceptions
|
||||
//
|
||||
// Tests _Unwind_Backtrace()
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
|
||||
// put intermediate function into another file so compiler does not optimze away
|
||||
extern int foo();
|
||||
|
||||
static const char* expected[] = { "bar", "foo", "main" };
|
||||
|
||||
static int step = 0;
|
||||
static _Unwind_Reason_Code handler(struct _Unwind_Context* context, void* ref)
|
||||
{
|
||||
if ( step > 2 )
|
||||
return _URC_NORMAL_STOP;
|
||||
struct dl_info dyldInfo;
|
||||
if ( dladdr((void*)_Unwind_GetIP(context), &dyldInfo) ) {
|
||||
if ( strcmp(dyldInfo.dli_sname, expected[step]) != 0 ) {
|
||||
fprintf(stderr, "unexpected frame %s\n", dyldInfo.dli_sname);
|
||||
exit(1);
|
||||
}
|
||||
++step;
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int bar()
|
||||
{
|
||||
_Unwind_Backtrace(&handler, NULL);
|
||||
return (step == 2);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
return foo();
|
||||
}
|
||||
|
54
testsuite/Unwind_ForcedUnwind.cxx
Normal file
54
testsuite/Unwind_ForcedUnwind.cxx
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
//
|
||||
// Tests _Unwind_ForcedUnwind()
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
|
||||
|
||||
static bool exceptionCaught = false;
|
||||
|
||||
|
||||
static _Unwind_Reason_Code stop_func(int version, _Unwind_Action actions, uint64_t exceptionClass,
|
||||
_Unwind_Exception* exceptionObject, _Unwind_Context* context, void* stop_parameter)
|
||||
{
|
||||
if ( actions & _UA_END_OF_STACK ) {
|
||||
if ( exceptionCaught )
|
||||
exit(0);
|
||||
else
|
||||
exit(1);
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
||||
void test()
|
||||
{
|
||||
try {
|
||||
_Unwind_Exception* except_obj = (_Unwind_Exception*)calloc(sizeof(_Unwind_Exception), 1);
|
||||
_Unwind_ForcedUnwind(except_obj, stop_func, NULL);
|
||||
}
|
||||
catch(...) {
|
||||
// forced unwindind should run this catch clause
|
||||
exceptionCaught = true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
return 1;
|
||||
}
|
||||
|
71
testsuite/backtrace.c
Normal file
71
testsuite/backtrace.c
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions -fomit-frame-pointer
|
||||
// TEST-OPTIONS: backtrace2.c -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64 -fomit-frame-pointer
|
||||
// TEST-OPTIONS: backtrace2.c -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: backtrace2.c -arch ppc -fexceptions
|
||||
//
|
||||
// Basic backtrace test
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
|
||||
static const char* other_expected[] = { "bar", "foo", "work", "_pthread_start", NULL, NULL };
|
||||
static const char* main_expected[] = { "bar", "foo", "main", NULL, NULL };
|
||||
|
||||
|
||||
// put intermediate function into another file so compiler does not optimze away
|
||||
extern int foo(const char** list);
|
||||
|
||||
|
||||
int bar(const char** list)
|
||||
{
|
||||
char functionName[64];
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t offset;
|
||||
|
||||
int index = 0;
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
do {
|
||||
unw_get_proc_name(&cursor, functionName, 64, &offset);
|
||||
//fprintf(stderr, "in function: %s\n", functionName);
|
||||
if ( (list[index] != NULL) && (strcmp(functionName, list[index]) != 0) ) {
|
||||
//fprintf(stderr, "unexpected function: %s\n", functionName);
|
||||
exit(1);
|
||||
}
|
||||
++index;
|
||||
} while (unw_step(&cursor) > 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* work(void* arg)
|
||||
{
|
||||
foo((const char**)arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
// test back traces on another thread
|
||||
pthread_t worker1;
|
||||
if ( pthread_create(&worker1, NULL, work, other_expected) != 0 ) {
|
||||
exit(0);
|
||||
}
|
||||
void* result;
|
||||
pthread_join(worker1, &result);
|
||||
|
||||
// test back traces on main thread
|
||||
return foo(main_expected);
|
||||
}
|
||||
|
7
testsuite/backtrace2.c
Normal file
7
testsuite/backtrace2.c
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
extern int bar(const char** list);
|
||||
|
||||
int foo(const char** list)
|
||||
{
|
||||
return bar(list);
|
||||
}
|
17
testsuite/dwarf_cache_dlclose.mk/Makefile
Normal file
17
testsuite/dwarf_cache_dlclose.mk/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
|
||||
|
||||
all:
|
||||
@g++ foo.cxx -dynamiclib -o libfoo.dylib -arch i386 -arch x86_64 -Wl,-no_compact_unwind
|
||||
@gcc main.c -arch i386 -o main-i386
|
||||
@./main-i386 && echo "PASS dwarf-cache-dlclose -arch i386"
|
||||
@gcc main.c -arch x86_64 -o main-x86_64
|
||||
@./main-x86_64 && echo "PASS dwarf-cache-dlclose -arch x86_64"
|
||||
# @gcc main.c -arch ppc -o main-ppc
|
||||
# @./main-ppc && echo "PASS dwarf-cache-dlclose -arch ppc"
|
||||
|
||||
clean:
|
||||
@rm -f libfoo.dylib main-i386 main-x86_64 main-ppc
|
||||
|
||||
|
20
testsuite/dwarf_cache_dlclose.mk/foo.cxx
Normal file
20
testsuite/dwarf_cache_dlclose.mk/foo.cxx
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#include <stdio.h>
|
||||
void bar()
|
||||
{
|
||||
throw "wow";
|
||||
}
|
||||
|
||||
extern "C" void foo();
|
||||
|
||||
void foo()
|
||||
{
|
||||
try {
|
||||
bar();
|
||||
}
|
||||
catch(...) {
|
||||
//fprintf(stderr, "caught\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
58
testsuite/dwarf_cache_dlclose.mk/main.c
Normal file
58
testsuite/dwarf_cache_dlclose.mk/main.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
#include <libunwind.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
|
||||
|
||||
|
||||
|
||||
typedef void (*FooProc)();
|
||||
static FooProc foo;
|
||||
|
||||
static bool fooInCache = false;
|
||||
static void callback(unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)
|
||||
{
|
||||
//fprintf(stderr, "ip_start = 0x%llX, ip_end = 0x%llX\n", ip_start, ip_end);
|
||||
if ( (unw_word_t)(long)foo == ip_start )
|
||||
fooInCache = true;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
void* handle = dlopen("libfoo.dylib", RTLD_FIRST);
|
||||
if ( handle == NULL ) {
|
||||
printf("FAIL: dlopen could not load libfoo.dylib\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
foo = (FooProc)dlsym(handle, "foo");
|
||||
if ( foo == NULL ) {
|
||||
printf("FAIL: dlsym could not find foo\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//fprintf(stderr, "foo=%p\n", foo);
|
||||
(*foo)();
|
||||
|
||||
// verify foo is in cache
|
||||
fooInCache = false;
|
||||
unw_iterate_dwarf_unwind_cache(&callback);
|
||||
if ( !fooInCache ) {
|
||||
printf("FAIL: foo is not in cache\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dlclose(handle);
|
||||
//fprintf(stderr, "dlclose\n");
|
||||
|
||||
// verify foo is no longer in cache
|
||||
fooInCache = false;
|
||||
unw_iterate_dwarf_unwind_cache(&callback);
|
||||
if ( fooInCache ){
|
||||
printf("FAIL: foo is still in cache\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
139
testsuite/dynamic_fde_registration.cxx
Normal file
139
testsuite/dynamic_fde_registration.cxx
Normal file
@ -0,0 +1,139 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <mach/mach.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
// private keymgr stuff
|
||||
#define KEYMGR_GCC3_DW2_OBJ_LIST 302
|
||||
extern "C" {
|
||||
extern void _keymgr_set_and_unlock_processwide_ptr(int key, void* ptr);
|
||||
extern void* _keymgr_get_and_lock_processwide_ptr(int key);
|
||||
};
|
||||
|
||||
|
||||
// undocumented libgcc "struct object"
|
||||
struct libgcc_object
|
||||
{
|
||||
void* start;
|
||||
void* unused1;
|
||||
void* unused2;
|
||||
void* fde;
|
||||
unsigned long encoding;
|
||||
void* fde_end;
|
||||
libgcc_object* next;
|
||||
};
|
||||
|
||||
// undocumented libgcc "struct km_object_info" referenced by KEYMGR_GCC3_DW2_OBJ_LIST
|
||||
struct libgcc_object_info {
|
||||
struct libgcc_object* seen_objects;
|
||||
struct libgcc_object* unseen_objects;
|
||||
unsigned spare[2];
|
||||
};
|
||||
|
||||
|
||||
// Some application have reverse engineer libgcc and do the equivalent
|
||||
// of my_keymgr_register_frame() to register dynamically created code.
|
||||
static void my_keymgr_register_frame(void* fde)
|
||||
{
|
||||
// acquire exclusive access to libgcc_object_info
|
||||
libgcc_object_info* head = (libgcc_object_info*)_keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
|
||||
|
||||
// create new object
|
||||
libgcc_object* ob = (libgcc_object*)calloc(sizeof(libgcc_object), 1);
|
||||
ob->fde = fde;
|
||||
|
||||
// insert new object into linked list
|
||||
ob->next = head->unseen_objects;
|
||||
head->unseen_objects = ob;
|
||||
|
||||
// release libgcc_object_info
|
||||
_keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void check(bool shouldFindMain)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t offset;
|
||||
bool foundMain = false;
|
||||
char functionName[256];
|
||||
//fprintf(stderr, "check(shouldFindMain=%d)\n", shouldFindMain);
|
||||
|
||||
int level = 1;
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
do {
|
||||
unw_get_proc_name(&cursor, functionName, 64, &offset);
|
||||
//fprintf(stderr, "level=%d in function: %s\n", level, functionName);
|
||||
if ( strcmp(functionName, "main") == 0 )
|
||||
foundMain = true;
|
||||
++level;
|
||||
strcpy(functionName, "junk");
|
||||
} while (unw_step(&cursor) > 0);
|
||||
|
||||
if ( foundMain == shouldFindMain )
|
||||
return;
|
||||
|
||||
fprintf(stderr, "failing because shouldFindMain=%d and foundMain=%d\n", shouldFindMain, foundMain);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void foo(bool shouldFindMain, void (*func)(bool))
|
||||
{
|
||||
(*func)(shouldFindMain);
|
||||
__asm__ volatile(""); // disable tail call optimization
|
||||
}
|
||||
|
||||
typedef void (*checkFuncProc)(bool shouldFindMain, void (*func)(bool));
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
struct dwarf_eh_bases junk;
|
||||
const void* foo_eh_src = _Unwind_Find_FDE((void*)((long)&foo + 1), &junk);
|
||||
// copy foo and its fde to a dynamically allocated buffer
|
||||
unsigned long deltaToFDE = (uintptr_t)foo_eh_src - (uintptr_t)&foo;
|
||||
unsigned long size = deltaToFDE + 100;
|
||||
size = ((size + 4095) & (-4096));
|
||||
vm_address_t addr = 0;
|
||||
if ( vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE) != KERN_SUCCESS )
|
||||
exit(1);
|
||||
memcpy((void*)addr, (void*)&foo, size);
|
||||
mprotect((void*)addr, size, PROT_READ|PROT_EXEC);
|
||||
// make pointer to copy of foo and copy of fde
|
||||
checkFuncProc checkFunc = (checkFuncProc)addr;
|
||||
void* foo_eh = (void*)(addr + deltaToFDE);
|
||||
|
||||
// call check() with unwind info unregistered, verify fails
|
||||
(*checkFunc)(false, check);
|
||||
|
||||
// call check() with unwind info registered, verify succeeds
|
||||
__register_frame(foo_eh);
|
||||
(*checkFunc)(true, check);
|
||||
|
||||
// call check() with unwind info unregistered, verify fails
|
||||
__deregister_frame(foo_eh);
|
||||
(*checkFunc)(false, check);
|
||||
|
||||
// call check() with unwind info added via keymgr, verify succeeds
|
||||
my_keymgr_register_frame(foo_eh);
|
||||
(*checkFunc)(true, check);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
39
testsuite/end_of_stack.c
Normal file
39
testsuite/end_of_stack.c
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions -fomit-frame-pointer
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -fomit-frame-pointer
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc -fexceptions
|
||||
|
||||
|
||||
//
|
||||
// Tests _Unwind_RaiseException() returns _URC_END_OF_STACK if there is nothing to catch the exception
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
|
||||
struct _Unwind_Exception ex;
|
||||
|
||||
int main()
|
||||
{
|
||||
ex.exception_class = ((uint64_t)'mymy' << 32) | (uint64_t)'exex';
|
||||
ex.exception_cleanup = NULL;
|
||||
ex.private_1 = 0;
|
||||
ex.private_2 = 0;
|
||||
|
||||
_Unwind_Reason_Code result = _Unwind_RaiseException(&ex);
|
||||
|
||||
if ( result == _URC_END_OF_STACK )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
240
testsuite/exception_32bit_lsda.s
Normal file
240
testsuite/exception_32bit_lsda.s
Normal file
@ -0,0 +1,240 @@
|
||||
|
||||
// TEST-OPTIONS: -arch x86_64 -lstdc++ -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
.section __TEXT,__text,regular,pure_instructions
|
||||
.globl __Z3foov
|
||||
.align 4, 0x90
|
||||
__Z3foov:
|
||||
Leh_func_begin1:
|
||||
pushq %rbp
|
||||
Ltmp0:
|
||||
movq %rsp, %rbp
|
||||
Ltmp1:
|
||||
subq $16, %rsp
|
||||
Ltmp2:
|
||||
movabsq $4, %rax
|
||||
movq %rax, %rdi
|
||||
callq ___cxa_allocate_exception
|
||||
movq %rax, -16(%rbp)
|
||||
movq -16(%rbp), %rax
|
||||
movl $10, (%rax)
|
||||
movq -16(%rbp), %rax
|
||||
movq __ZTIi@GOTPCREL(%rip), %rcx
|
||||
leaq (%rcx), %rcx
|
||||
movabsq $0, %rdx
|
||||
movq %rax, %rdi
|
||||
movq %rcx, %rsi
|
||||
callq ___cxa_throw
|
||||
Leh_func_end1:
|
||||
|
||||
.globl _main
|
||||
.align 4, 0x90
|
||||
_main:
|
||||
Leh_func_begin2:
|
||||
pushq %rbp
|
||||
Ltmp6:
|
||||
movq %rsp, %rbp
|
||||
Ltmp7:
|
||||
subq $48, %rsp
|
||||
Ltmp8:
|
||||
movl $1, -28(%rbp)
|
||||
movl $2, -28(%rbp)
|
||||
Ltmp3:
|
||||
callq __Z3foov
|
||||
Ltmp4:
|
||||
jmp LBB2_1
|
||||
LBB2_1:
|
||||
movl $3, -28(%rbp)
|
||||
jmp LBB2_10
|
||||
LBB2_2:
|
||||
movq -40(%rbp), %rax
|
||||
movq %rax, %rdi
|
||||
callq ___cxa_begin_catch
|
||||
movq %rax, -24(%rbp)
|
||||
movq -24(%rbp), %rax
|
||||
movl (%rax), %eax
|
||||
movl %eax, -32(%rbp)
|
||||
movl -28(%rbp), %eax
|
||||
cmpl $2, %eax
|
||||
je LBB2_4
|
||||
movl $1, -12(%rbp)
|
||||
movl -12(%rbp), %eax
|
||||
movl %eax, -12(%rbp)
|
||||
movl -12(%rbp), %eax
|
||||
movl %eax, -12(%rbp)
|
||||
movl $0, -8(%rbp)
|
||||
jmp LBB2_7
|
||||
LBB2_4:
|
||||
movl -32(%rbp), %eax
|
||||
cmpl $10, %eax
|
||||
je LBB2_6
|
||||
movl $1, -12(%rbp)
|
||||
movl -12(%rbp), %eax
|
||||
movl %eax, -12(%rbp)
|
||||
movl -12(%rbp), %eax
|
||||
movl %eax, -12(%rbp)
|
||||
movl $0, -8(%rbp)
|
||||
jmp LBB2_7
|
||||
LBB2_6:
|
||||
movl $4, -28(%rbp)
|
||||
movl $1, -8(%rbp)
|
||||
LBB2_7:
|
||||
callq ___cxa_end_catch
|
||||
movl -8(%rbp), %eax
|
||||
cmpl $1, %eax
|
||||
jne LBB2_9
|
||||
jmp LBB2_10
|
||||
LBB2_9:
|
||||
jmp LBB2_13
|
||||
LBB2_10:
|
||||
movl -28(%rbp), %eax
|
||||
cmpl $4, %eax
|
||||
jne LBB2_12
|
||||
movl $0, -12(%rbp)
|
||||
jmp LBB2_13
|
||||
LBB2_12:
|
||||
movl $1, -12(%rbp)
|
||||
LBB2_13:
|
||||
movl -12(%rbp), %eax
|
||||
movl %eax, -4(%rbp)
|
||||
movl -4(%rbp), %eax
|
||||
addq $48, %rsp
|
||||
popq %rbp
|
||||
ret
|
||||
LBB2_15:
|
||||
Ltmp5:
|
||||
movq %rax, -40(%rbp)
|
||||
movq -40(%rbp), %rax
|
||||
movl %edx, %eax
|
||||
movl %eax, -44(%rbp)
|
||||
movl $2, %eax
|
||||
movl -44(%rbp), %ecx
|
||||
cmpl %eax, %ecx
|
||||
je LBB2_2
|
||||
movq -40(%rbp), %rax
|
||||
movq %rax, %rdi
|
||||
callq __Unwind_Resume_or_Rethrow
|
||||
Leh_func_end2:
|
||||
|
||||
|
||||
.section __TEXT,__gcc_except_tab
|
||||
.align 2
|
||||
GCC_except_table2:
|
||||
Lexception2:
|
||||
.byte 255
|
||||
.byte 155
|
||||
.byte 168
|
||||
.space 1
|
||||
.byte 3
|
||||
.byte 26
|
||||
Lset0 = Ltmp3-Leh_func_begin2
|
||||
.long Lset0
|
||||
Lset1 = Ltmp4-Ltmp3
|
||||
.long Lset1
|
||||
Lset2 = Ltmp5-Leh_func_begin2
|
||||
.long Lset2
|
||||
.byte 3
|
||||
Lset3 = Ltmp4-Leh_func_begin2
|
||||
.long Lset3
|
||||
Lset4 = Leh_func_end2-Ltmp4
|
||||
.long Lset4
|
||||
.long 0
|
||||
.byte 0
|
||||
|
||||
|
||||
.byte 1
|
||||
.byte 0
|
||||
|
||||
.byte 2
|
||||
.byte 125
|
||||
|
||||
.long __ZTIi@GOTPCREL+4
|
||||
.long 0
|
||||
.align 2
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame0:
|
||||
Lsection_eh_frame:
|
||||
Leh_frame_common:
|
||||
Lset5 = Leh_frame_common_end-Leh_frame_common_begin
|
||||
.long Lset5
|
||||
Leh_frame_common_begin:
|
||||
.long 0
|
||||
.byte 1
|
||||
.asciz "zPLR"
|
||||
.byte 1
|
||||
.byte 120
|
||||
.byte 16
|
||||
.byte 7
|
||||
.byte 155
|
||||
.long ___gxx_personality_v0@GOTPCREL+4
|
||||
.byte 0x1B // lsda encoding DW_EH_PE_pcrel + DW_EH_PE_sdata4
|
||||
.byte 16
|
||||
.byte 12
|
||||
.byte 7
|
||||
.byte 8
|
||||
.byte 144
|
||||
.byte 1
|
||||
.align 3
|
||||
Leh_frame_common_end:
|
||||
|
||||
.globl __Z3foov.eh
|
||||
__Z3foov.eh:
|
||||
Lset6 = Leh_frame_end1-Leh_frame_begin1
|
||||
.long Lset6
|
||||
Leh_frame_begin1:
|
||||
Lset7 = Leh_frame_begin1-Leh_frame_common
|
||||
.long Lset7
|
||||
Ltmp9:
|
||||
.quad Leh_func_begin1-Ltmp9
|
||||
Lset8 = Leh_func_end1-Leh_func_begin1
|
||||
.quad Lset8
|
||||
.byte 4
|
||||
.long 0
|
||||
.byte 4
|
||||
Lset9 = Ltmp0-Leh_func_begin1
|
||||
.long Lset9
|
||||
.byte 14
|
||||
.byte 16
|
||||
.byte 134
|
||||
.byte 2
|
||||
.byte 4
|
||||
Lset10 = Ltmp1-Ltmp0
|
||||
.long Lset10
|
||||
.byte 13
|
||||
.byte 6
|
||||
.align 3
|
||||
Leh_frame_end1:
|
||||
|
||||
.globl _main.eh
|
||||
_main.eh:
|
||||
Lset11 = Leh_frame_end2-Leh_frame_begin2
|
||||
.long Lset11
|
||||
Leh_frame_begin2:
|
||||
Lset12 = Leh_frame_begin2-Leh_frame_common
|
||||
.long Lset12
|
||||
Ltmp10:
|
||||
.quad Leh_func_begin2-Ltmp10
|
||||
Lset13 = Leh_func_end2-Leh_func_begin2
|
||||
.quad Lset13
|
||||
.byte 4
|
||||
Ltmp11:
|
||||
.long Lexception2-Ltmp11
|
||||
.byte 4
|
||||
Lset14 = Ltmp6-Leh_func_begin2
|
||||
.long Lset14
|
||||
.byte 14
|
||||
.byte 16
|
||||
.byte 134
|
||||
.byte 2
|
||||
.byte 4
|
||||
Lset15 = Ltmp7-Ltmp6
|
||||
.long Lset15
|
||||
.byte 13
|
||||
.byte 6
|
||||
.align 3
|
||||
Leh_frame_end2:
|
||||
|
||||
|
||||
.subsections_via_symbols
|
33
testsuite/exception_basic.cxx
Normal file
33
testsuite/exception_basic.cxx
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
|
||||
int foo() { throw 10; }
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int state = 1;
|
||||
try {
|
||||
state = 2;
|
||||
foo();
|
||||
state = 3;
|
||||
}
|
||||
catch (int x) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( x != 10 )
|
||||
return 1;
|
||||
state = 4;
|
||||
}
|
||||
|
||||
if ( state == 4 )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
54
testsuite/exception_catch_and_throw.cxx
Normal file
54
testsuite/exception_catch_and_throw.cxx
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int global = 0;
|
||||
|
||||
int bar()
|
||||
{
|
||||
global = 1;
|
||||
throw 10;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void foo()
|
||||
{
|
||||
try {
|
||||
bar();
|
||||
}
|
||||
catch(int x) {
|
||||
global = 2;
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int state = 1;
|
||||
try {
|
||||
state = 2;
|
||||
foo();
|
||||
state = 3;
|
||||
}
|
||||
catch (int x) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( x != 10 )
|
||||
return 1;
|
||||
state = 4;
|
||||
}
|
||||
|
||||
if ( (state == 4) && (global == 2) )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
52
testsuite/exception_missing_eh.cxx
Normal file
52
testsuite/exception_missing_eh.cxx
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
|
||||
// TEST-OPTIONS: -x c exception_missing_eh2.c -arch i386
|
||||
// TEST-OPTIONS: -x c exception_missing_eh2.c -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -x c exception_missing_eh2.c -arch ppc
|
||||
// TEST-OPTIONS: exception_missing_eh2_x86_64.s -arch x86_64
|
||||
// TEST-OPTIONS: exception_missing_eh2_x86_64.s -arch x86_64 -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
extern "C" {
|
||||
extern int bar();
|
||||
extern int foo();
|
||||
}
|
||||
|
||||
|
||||
int foo() { throw 10; }
|
||||
|
||||
static void term()
|
||||
{
|
||||
// terminate called, as we want
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
std::set_terminate(term);
|
||||
|
||||
int state = 1;
|
||||
try {
|
||||
state = 2;
|
||||
// bar() calls foo() which throws
|
||||
// but, bar is missing eh info, so terminate() is called
|
||||
bar();
|
||||
state = 3;
|
||||
}
|
||||
catch (int x) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( x != 10 )
|
||||
return 1;
|
||||
state = 4;
|
||||
}
|
||||
|
||||
// should not get here
|
||||
exit(1);
|
||||
}
|
||||
|
14
testsuite/exception_missing_eh2.c
Normal file
14
testsuite/exception_missing_eh2.c
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
// bar() calls foo()
|
||||
// this is in a separate file because we want bar() to not have eh info
|
||||
|
||||
extern int foo();
|
||||
|
||||
int global;
|
||||
|
||||
int bar() {
|
||||
int x = foo();
|
||||
++global; // to prevent tail call optimization
|
||||
return x;
|
||||
}
|
13
testsuite/exception_missing_eh2_x86_64.s
Normal file
13
testsuite/exception_missing_eh2_x86_64.s
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
/* Need assembly to create bar() without eh info */
|
||||
|
||||
.text
|
||||
.globl _bar
|
||||
_bar:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
subq $16, %rsp
|
||||
movl $0, %eax
|
||||
call _foo
|
||||
leave
|
||||
ret
|
54
testsuite/exception_rethrow.cxx
Normal file
54
testsuite/exception_rethrow.cxx
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int global = 0;
|
||||
|
||||
int bar()
|
||||
{
|
||||
global = 1;
|
||||
throw 10;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void foo()
|
||||
{
|
||||
try {
|
||||
bar();
|
||||
}
|
||||
catch(int x) {
|
||||
global = 2;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int state = 1;
|
||||
try {
|
||||
state = 2;
|
||||
foo();
|
||||
state = 3;
|
||||
}
|
||||
catch (int x) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( x != 10 )
|
||||
return 1;
|
||||
state = 4;
|
||||
}
|
||||
|
||||
if ( (state == 4) && (global == 2) )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
57
testsuite/exception_signal.cxx
Normal file
57
testsuite/exception_signal.cxx
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <new>
|
||||
|
||||
void segfault(int sig)
|
||||
{
|
||||
::signal(SIGBUS, SIG_DFL);
|
||||
::signal(SIGSEGV, SIG_DFL);
|
||||
|
||||
//fprintf(stderr, "bus error handler for pid=%d\n", getpid());
|
||||
//sleep(30);
|
||||
throw "seg fault";
|
||||
}
|
||||
|
||||
|
||||
__attribute__((noinline)) void boom(int* p)
|
||||
{
|
||||
// do allocation, so compiler won't optimize away catch clause in main()
|
||||
int* x = new int[100];
|
||||
*x = *p;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
::signal(SIGBUS, segfault);
|
||||
::signal(SIGSEGV, segfault);
|
||||
|
||||
int state = 1;
|
||||
try {
|
||||
state = 2;
|
||||
boom(NULL);
|
||||
state = 3;
|
||||
}
|
||||
catch (const char* msg) {
|
||||
//fprintf(stderr, "caught %s\n", msg);
|
||||
if ( state != 2 )
|
||||
exit(1);
|
||||
state = 4;
|
||||
}
|
||||
catch(...) {
|
||||
//fprintf(stderr, "caught ...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( state == 4 )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
48
testsuite/find_enclosing.c
Normal file
48
testsuite/find_enclosing.c
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions -fomit-frame-pointer -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64 -fomit-frame-pointer -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc -fexceptions
|
||||
//
|
||||
// Basic _Unwind_FindEnclosingFunction test
|
||||
//
|
||||
// _Unwind_FindEnclosingFunction() is supposed to return the start of a
|
||||
// function given an address in the function. It uses FDE info.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
int bar(int x)
|
||||
{
|
||||
// dummy call to force dwarf info generation
|
||||
_Unwind_GetIP(NULL);
|
||||
return x + 20;
|
||||
}
|
||||
|
||||
int foo(int x)
|
||||
{
|
||||
// dummy call to force dwarf info generation
|
||||
_Unwind_GetIP(NULL);
|
||||
return x + 10;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t* addrInBar = (uint8_t*)bar + 4;
|
||||
uint8_t* addrInFoo = (uint8_t*)foo + 4;
|
||||
if ( _Unwind_FindEnclosingFunction(addrInBar) != &bar )
|
||||
return 1;
|
||||
if ( _Unwind_FindEnclosingFunction(addrInFoo) != &foo )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
50
testsuite/objc_alt_handler.m
Normal file
50
testsuite/objc_alt_handler.m
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
// TEST-OPTIONS: -arch x86_64 -framework Foundation
|
||||
// TEST-OPTIONS: -arch x86_64 -framework Foundation -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
// private SPI for AppKit
|
||||
extern int _NSAddAltHandler2(void (*proc)(NSException* exc, void* context), void* context);
|
||||
|
||||
|
||||
int foo()
|
||||
{
|
||||
@throw [NSException exceptionWithName:NSGenericException reason:@"many" userInfo:nil];
|
||||
}
|
||||
|
||||
static void handler(NSException* exc, void* context)
|
||||
{
|
||||
int* paltState = (int*)context;
|
||||
*paltState = 1;
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
int state = 1;
|
||||
int altState = 0;
|
||||
@try {
|
||||
_NSAddAltHandler2(handler, &altState);
|
||||
state = 2;
|
||||
foo();
|
||||
state = 3;
|
||||
}
|
||||
@catch(id exception) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( altState == 0 )
|
||||
return 1;
|
||||
if ( [[exception name] isEqualToString:NSGenericException] )
|
||||
state = 4;
|
||||
}
|
||||
|
||||
if ( state == 4 )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
36
testsuite/objc_exception_basic.m
Normal file
36
testsuite/objc_exception_basic.m
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
// TEST-OPTIONS: -arch x86_64 -framework Foundation
|
||||
// TEST-OPTIONS: -arch x86_64 -framework Foundation -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
int foo()
|
||||
{
|
||||
@throw [NSException exceptionWithName:NSGenericException reason:@"many" userInfo:nil];
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
int state = 1;
|
||||
@try {
|
||||
state = 2;
|
||||
foo();
|
||||
state = 3;
|
||||
}
|
||||
@catch(id exception) {
|
||||
if ( state != 2 )
|
||||
return 1;
|
||||
if ( [[exception name] isEqualToString:NSGenericException] )
|
||||
state = 4;
|
||||
}
|
||||
|
||||
if ( state == 4 )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
170
testsuite/personality.cxx
Normal file
170
testsuite/personality.cxx
Normal file
@ -0,0 +1,170 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
static __personality_routine realPersonality = (__personality_routine)dlsym(RTLD_DEFAULT, "__gxx_personality_v0");
|
||||
|
||||
int count = 0;
|
||||
|
||||
const char* actionString(_Unwind_Action act)
|
||||
{
|
||||
static char buffer[100];
|
||||
buffer[0] = '\0';
|
||||
|
||||
if ( act & _UA_SEARCH_PHASE )
|
||||
strcat(buffer, "_UA_SEARCH_PHASE ");
|
||||
if ( act & _UA_CLEANUP_PHASE )
|
||||
strcat(buffer, "_UA_CLEANUP_PHASE ");
|
||||
if ( act & _UA_HANDLER_FRAME )
|
||||
strcat(buffer, "_UA_HANDLER_FRAME ");
|
||||
if ( act & _UA_FORCE_UNWIND )
|
||||
strcat(buffer, "_UA_FORCE_UNWIND ");
|
||||
if ( act & _UA_END_OF_STACK )
|
||||
strcat(buffer, "_UA_END_OF_STACK ");
|
||||
if ( act & 0xFFFFFFE0 )
|
||||
strcat(buffer, "unknown bits ");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* reasonString(_Unwind_Reason_Code reason)
|
||||
{
|
||||
switch (reason) {
|
||||
case _URC_NO_REASON:
|
||||
return "_URC_NO_REASON";
|
||||
case _URC_FOREIGN_EXCEPTION_CAUGHT:
|
||||
return "_URC_FOREIGN_EXCEPTION_CAUGHT";
|
||||
case _URC_FATAL_PHASE2_ERROR:
|
||||
return "_URC_FATAL_PHASE2_ERROR";
|
||||
case _URC_FATAL_PHASE1_ERROR:
|
||||
return "_URC_FATAL_PHASE1_ERROR";
|
||||
case _URC_NORMAL_STOP:
|
||||
return "_URC_NORMAL_STOP";
|
||||
case _URC_END_OF_STACK:
|
||||
return "_URC_END_OF_STACK";
|
||||
case _URC_HANDLER_FOUND:
|
||||
return "_URC_HANDLER_FOUND";
|
||||
case _URC_INSTALL_CONTEXT:
|
||||
return "_URC_INSTALL_CONTEXT";
|
||||
case _URC_CONTINUE_UNWIND:
|
||||
return "_URC_CONTINUE_UNWIND";
|
||||
}
|
||||
return "unknown reason code";
|
||||
}
|
||||
|
||||
bool fooCaught = false;
|
||||
bool mainInnerCaught = false;
|
||||
bool mainOuterCaught = false;
|
||||
|
||||
struct Expected {
|
||||
bool fooCaught;
|
||||
bool mainInnerCaught;
|
||||
bool mainOuterCaught;
|
||||
_Unwind_Action action;
|
||||
_Unwind_Reason_Code result;
|
||||
};
|
||||
|
||||
#define _UA_CLEANUP_PHASE_HANDLER_FRAME (_Unwind_Action)(_UA_CLEANUP_PHASE|_UA_HANDLER_FRAME)
|
||||
|
||||
const Expected shouldBe[] = {
|
||||
{ false, false, false, _UA_SEARCH_PHASE, _URC_HANDLER_FOUND },
|
||||
{ false, false, false, _UA_CLEANUP_PHASE_HANDLER_FRAME, _URC_INSTALL_CONTEXT },
|
||||
{ true, false, false, _UA_SEARCH_PHASE, _URC_CONTINUE_UNWIND },
|
||||
{ true, false, false, _UA_SEARCH_PHASE, _URC_HANDLER_FOUND },
|
||||
{ true, false, false, _UA_CLEANUP_PHASE, _URC_INSTALL_CONTEXT },
|
||||
{ true, false, false, _UA_CLEANUP_PHASE, _URC_CONTINUE_UNWIND },
|
||||
{ true, false, false, _UA_CLEANUP_PHASE_HANDLER_FRAME, _URC_INSTALL_CONTEXT },
|
||||
{ true, true, false, _UA_SEARCH_PHASE, _URC_HANDLER_FOUND },
|
||||
{ true, true, false, _UA_CLEANUP_PHASE_HANDLER_FRAME, _URC_INSTALL_CONTEXT }
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
__attribute__((visibility("hidden"))) _Unwind_Reason_Code __gxx_personality_v0(
|
||||
int version, _Unwind_Action actions, uint64_t exceptionClass,
|
||||
struct _Unwind_Exception* exceptionObject, _Unwind_Context* context)
|
||||
{
|
||||
|
||||
_Unwind_Reason_Code result = (*realPersonality)(version, actions, exceptionClass,
|
||||
exceptionObject, context);
|
||||
//fprintf(stderr, "fooCaught=%d, mainInnerCaught=%d, mainOuterCaught=%d, ",
|
||||
// fooCaught, mainInnerCaught, mainOuterCaught);
|
||||
//fprintf(stderr, "personality(%d, %s, 0x%llX, %p, %p) => %s\n", version, actionString(actions),
|
||||
// exceptionClass, exceptionObject, context, reasonString(result));
|
||||
if ( shouldBe[count].fooCaught != fooCaught ) {
|
||||
fprintf(stderr, "count=%d, fooCaught=%d\n", count, fooCaught);
|
||||
abort();
|
||||
}
|
||||
if ( shouldBe[count].mainInnerCaught != mainInnerCaught ) {
|
||||
fprintf(stderr, "count=%d, mainInnerCaught=%d\n", count, mainInnerCaught);
|
||||
abort();
|
||||
}
|
||||
if ( shouldBe[count].mainOuterCaught != mainOuterCaught ) {
|
||||
fprintf(stderr, "count=%d, mainOuterCaught=%d\n", count, mainOuterCaught);
|
||||
abort();
|
||||
}
|
||||
if ( shouldBe[count].action != actions ) {
|
||||
fprintf(stderr, "count=%d, actions=%s\n", count, actionString(actions));
|
||||
abort();
|
||||
}
|
||||
if ( shouldBe[count].result != result ) {
|
||||
fprintf(stderr, "count=%d, result=%s\n", count, reasonString(result));
|
||||
abort();
|
||||
}
|
||||
if ( count++ > 12 )
|
||||
abort();
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int __attribute__((noinline)) bar()
|
||||
{
|
||||
throw 10;
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((noinline)) foo()
|
||||
{
|
||||
try {
|
||||
bar();
|
||||
}
|
||||
catch(int x) {
|
||||
fooCaught = true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
try {
|
||||
foo();
|
||||
}
|
||||
catch (int x) {
|
||||
mainInnerCaught = true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
mainOuterCaught = true;
|
||||
}
|
||||
if ( count != 9 ) {
|
||||
fprintf(stderr, "count=%d\n", count);
|
||||
abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
40
testsuite/rethrow_missing_catch.cxx
Normal file
40
testsuite/rethrow_missing_catch.cxx
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
|
||||
int foo()
|
||||
{
|
||||
try {
|
||||
throw 10;
|
||||
}
|
||||
catch (...) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
static void term()
|
||||
{
|
||||
// terminate called, as we want
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
std::set_terminate(term);
|
||||
|
||||
foo();
|
||||
|
||||
// should not get here
|
||||
exit(1);
|
||||
}
|
||||
|
108
testsuite/run-all-tests.pl
Normal file
108
testsuite/run-all-tests.pl
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use File::stat;
|
||||
use Cwd;
|
||||
|
||||
|
||||
my $testCaseFilter = '*';
|
||||
if ( $#ARGV == 0 ) {
|
||||
$testCaseFilter = $ARGV[0];
|
||||
}
|
||||
|
||||
my $useLocalDylib = 0;
|
||||
my $headerPath = "-I../include -I../src";
|
||||
if ( stat('../build/Debug/libunwind.dylib') ) {
|
||||
printf "### running with ../build/Debug/libunwind.dylib ###\n";
|
||||
$useLocalDylib = 1;
|
||||
}
|
||||
|
||||
my $canRunPPC = 0;
|
||||
if ( stat('/usr/libexec/oah/translate') ) {
|
||||
# $canRunPPC = 1;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Search current directory for all files with TEST-OPTIONS: comments
|
||||
# Compile and link each file with specified options
|
||||
# Execute result and print PASS or FAIL
|
||||
#
|
||||
my $path = shift;
|
||||
# get list of dylibs linked against
|
||||
open(FILE, "grep -H 'TEST-OPTIONS:' $testCaseFilter |");
|
||||
$/ = "\n";
|
||||
while ( <FILE> ) {
|
||||
if ($_ =~ m/^(.+):.+TEST-OPTIONS:(.+)/) {
|
||||
my $file = $1;
|
||||
my $options = "$2";
|
||||
my $ppc = 0;
|
||||
if ( $options =~ /arch ppc/ ) {
|
||||
$ppc = 1;
|
||||
}
|
||||
if ( $file !~ "run-all-tests.pl" ) {
|
||||
my $exit;
|
||||
if ( $ppc && !$canRunPPC ) {
|
||||
# don't try to build ppc tests
|
||||
}
|
||||
elsif ( $file =~ /^(.+)\.cxx/ ) {
|
||||
#printf "c++ $file $options $headerPath -o /tmp/run-all-tests.a.out\n";
|
||||
$exit = system("c++ $file $options $headerPath -o /tmp/run-all-tests.a.out");
|
||||
}
|
||||
else {
|
||||
#printf "cc $file $options $headerPath -o /tmp/run-all-tests.a.out\n";
|
||||
$exit = system("cc $file $options $headerPath -o /tmp/run-all-tests.a.out");
|
||||
}
|
||||
if ( $ppc && ($useLocalDylib || !$canRunPPC) ) {
|
||||
#printf "SKIP $file $options\n";
|
||||
}
|
||||
elsif ( $exit == 0 ) {
|
||||
if ( $useLocalDylib ) {
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = '../build/Debug';
|
||||
}
|
||||
my $exit = system("/tmp/run-all-tests.a.out");
|
||||
if ( $useLocalDylib ) {
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = '';
|
||||
}
|
||||
if ( $exit == 0 ) {
|
||||
printf "PASS $file $options\n";
|
||||
}
|
||||
else {
|
||||
printf "FAIL $file $options (runtime failure)\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf "FAIL $file $options (could not compile)\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close FILE;
|
||||
|
||||
#
|
||||
# Search for .mk directories and run make in each one
|
||||
#
|
||||
my $cwd = getcwd();
|
||||
open(FILE, "ls -1 |");
|
||||
$/ = "\n";
|
||||
while ( <FILE> ) {
|
||||
if ($_ =~ m/^(.+\.mk)$/) {
|
||||
my $dir = $1;
|
||||
if ( ($testCaseFilter =~ /\*/) || ($dir =~ /$testCaseFilter/) ) {
|
||||
if ( $useLocalDylib ) {
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = "$cwd/../build/Debug";
|
||||
}
|
||||
my $exit = system("cd $dir && make");
|
||||
if ( $useLocalDylib ) {
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = '';
|
||||
}
|
||||
system("cd $dir && make clean");
|
||||
}
|
||||
}
|
||||
}
|
||||
close FILE;
|
||||
|
||||
|
||||
|
||||
|
31
testsuite/terminate_is_handler.cxx
Normal file
31
testsuite/terminate_is_handler.cxx
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
// TEST-OPTIONS: -arch i386
|
||||
// TEST-OPTIONS: -arch i386 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <exception>
|
||||
|
||||
|
||||
void my_terminate() {
|
||||
try {
|
||||
throw;
|
||||
} catch (char *s) {
|
||||
if ( (s == NULL) || (strcmp(s, "my exception") != 0) )
|
||||
exit(1);
|
||||
//printf("caught rethrown %p %s\n", s, s);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
std::set_terminate(&my_terminate);
|
||||
throw "my exception";
|
||||
}
|
||||
|
26
testsuite/unw_getcontext.c
Normal file
26
testsuite/unw_getcontext.c
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
//
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions
|
||||
// TEST-OPTIONS: -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch x86_64
|
||||
// TEST-OPTIONS: -arch x86_64 -Wl,-no_compact_unwind
|
||||
// TEST-OPTIONS: -arch ppc -fexceptions
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// verify unw_getcontext() returns no UNW_ESUCCESS
|
||||
unw_context_t uc;
|
||||
if ( unw_getcontext(&uc) == UNW_ESUCCESS )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
46
testsuite/unwind_test_main.c
Normal file
46
testsuite/unwind_test_main.c
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libunwind.h"
|
||||
|
||||
extern int unwind_tester(void*);
|
||||
extern void* unwind_tester_list[];
|
||||
|
||||
int main()
|
||||
{
|
||||
// loop over all function pointers in unwind_tester_list
|
||||
// and call unwind_tester() on each one. If it returns
|
||||
// non-zero, then that test failed.
|
||||
void** p;
|
||||
for(p=unwind_tester_list; *p != NULL; ++p) {
|
||||
//fprintf(stderr, "unwind_tester(%p)\n", *p);
|
||||
if ( unwind_tester(*p) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// called by test function
|
||||
// we unwind through the test function
|
||||
// and resume at caller (unwind_tester)
|
||||
void uwind_to_main()
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t offset;
|
||||
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
if ( unw_step(&cursor) > 0 ) {
|
||||
// now in test function
|
||||
if ( unw_step(&cursor) > 0 ) {
|
||||
// now in unwind_tester
|
||||
unw_resume(&cursor);
|
||||
}
|
||||
}
|
||||
// error if we got here
|
||||
exit(1);
|
||||
}
|
||||
|
502
testsuite/unwind_test_ppc.s
Normal file
502
testsuite/unwind_test_ppc.s
Normal file
@ -0,0 +1,502 @@
|
||||
|
||||
#
|
||||
# This is a generic function to test that restoring registers during unwinding work correctly.
|
||||
#
|
||||
|
||||
.literal4
|
||||
.align 2
|
||||
LC14: .long 1096810496
|
||||
LC15: .long 1097859072
|
||||
LC16: .long 1098907648
|
||||
LC17: .long 1099431936
|
||||
LC18: .long 1099956224
|
||||
LC19: .long 1100480512
|
||||
LC20: .long 1101004800
|
||||
LC21: .long 1101529088
|
||||
LC22: .long 1102053376
|
||||
LC23: .long 1102577664
|
||||
LC24: .long 1103101952
|
||||
LC25: .long 1103626240
|
||||
LC26: .long 1104150528
|
||||
LC27: .long 1104674816
|
||||
LC28: .long 1105199104
|
||||
LC29: .long 1105723392
|
||||
LC30: .long 1106247680
|
||||
LC31: .long 1106771968
|
||||
|
||||
.literal16
|
||||
LV23: .long 0x23232323, 0x23232322, 0x23232321, 0x23232320
|
||||
LV24: .long 0x24242424, 0x24242422, 0x24242421, 0x24242420
|
||||
LV25: .long 0x25252525, 0x25252522, 0x25252521, 0x25252520
|
||||
LV26: .long 0x26262626, 0x26262622, 0x26262621, 0x26262620
|
||||
LV27: .long 0x27272727, 0x27272722, 0x27272721, 0x27272720
|
||||
LV28: .long 0x28282828, 0x28282822, 0x28282821, 0x28282820
|
||||
LV29: .long 0x29292929, 0x29292922, 0x29292921, 0x29292920
|
||||
LV30: .long 0x30303030, 0x30303022, 0x30303021, 0x30303020
|
||||
LV31: .long 0x31313131, 0x31313122, 0x31313121, 0x31313120
|
||||
|
||||
.text
|
||||
.globl _unwind_tester
|
||||
_unwind_tester:
|
||||
LFB2:
|
||||
mflr r0
|
||||
LCFI43:
|
||||
bl saveFP ; save f14-f31
|
||||
LCFI44:
|
||||
stmw r13,-220(r1)
|
||||
LCFI45:
|
||||
stwu r1,-336(r1)
|
||||
LCFI46:
|
||||
|
||||
# load magic values into non-volatile registers
|
||||
lis r31,0x3333
|
||||
ori r31,r31,0x3131
|
||||
lis r30,0x3333
|
||||
ori r30,r30,0x3030
|
||||
lis r29,0x2222
|
||||
ori r29,r29,0x2929
|
||||
lis r28,0x2222
|
||||
ori r28,r28,0x2828
|
||||
lis r27,0x2222
|
||||
ori r27,r27,0x2727
|
||||
lis r26,0x2222
|
||||
ori r26,r26,0x2626
|
||||
lis r25,0x2222
|
||||
ori r25,r25,0x2525
|
||||
lis r24,0x2222
|
||||
ori r24,r24,0x2424
|
||||
lis r23,0x2222
|
||||
ori r23,r23,0x2323
|
||||
lis r22,0x2222
|
||||
ori r22,r22,0x2222
|
||||
lis r21,0x2222
|
||||
ori r21,r21,0x2121
|
||||
lis r20,0x2222
|
||||
ori r20,r20,0x2020
|
||||
lis r19,0x1111
|
||||
ori r19,r19,0x1919
|
||||
lis r18,0x1111
|
||||
ori r18,r18,0x1818
|
||||
lis r17,0x1111
|
||||
ori r17,r17,0x1717
|
||||
lis r16,0x1111
|
||||
ori r16,r16,0x1616
|
||||
lis r15,0x1111
|
||||
ori r15,r15,0x1515
|
||||
lis r14,0x1111
|
||||
ori r14,r14,0x1414
|
||||
lis r13,0x1111
|
||||
ori r13,r13,0x1313
|
||||
|
||||
lis r2,ha16(LC14)
|
||||
lfs f14,lo16(LC14)(r2)
|
||||
lis r2,ha16(LC15)
|
||||
lfs f15,lo16(LC15)(r2)
|
||||
lis r2,ha16(LC16)
|
||||
lfs f16,lo16(LC16)(r2)
|
||||
lis r2,ha16(LC17)
|
||||
lfs f17,lo16(LC17)(r2)
|
||||
lis r2,ha16(LC18)
|
||||
lfs f18,lo16(LC18)(r2)
|
||||
lis r2,ha16(LC19)
|
||||
lfs f19,lo16(LC19)(r2)
|
||||
lis r2,ha16(LC20)
|
||||
lfs f20,lo16(LC20)(r2)
|
||||
lis r2,ha16(LC21)
|
||||
lfs f21,lo16(LC21)(r2)
|
||||
lis r2,ha16(LC22)
|
||||
lfs f22,lo16(LC22)(r2)
|
||||
lis r2,ha16(LC23)
|
||||
lfs f23,lo16(LC23)(r2)
|
||||
lis r2,ha16(LC24)
|
||||
lfs f24,lo16(LC24)(r2)
|
||||
lis r2,ha16(LC25)
|
||||
lfs f25,lo16(LC25)(r2)
|
||||
lis r2,ha16(LC26)
|
||||
lfs f26,lo16(LC26)(r2)
|
||||
lis r2,ha16(LC27)
|
||||
lfs f27,lo16(LC27)(r2)
|
||||
lis r2,ha16(LC28)
|
||||
lfs f28,lo16(LC28)(r2)
|
||||
lis r2,ha16(LC29)
|
||||
lfs f29,lo16(LC29)(r2)
|
||||
lis r2,ha16(LC30)
|
||||
lfs f30,lo16(LC30)(r2)
|
||||
lis r2,ha16(LC31)
|
||||
lfs f31,lo16(LC31)(r2)
|
||||
|
||||
lis r2,ha16(LV23)
|
||||
la r2,lo16(LV23)(r2)
|
||||
lvx v23,0,r2
|
||||
lis r2,ha16(LV24)
|
||||
la r2,lo16(LV24)(r2)
|
||||
lvx v24,0,r2
|
||||
lis r2,ha16(LV25)
|
||||
la r2,lo16(LV25)(r2)
|
||||
lvx v25,0,r2
|
||||
lis r2,ha16(LV26)
|
||||
la r2,lo16(LV26)(r2)
|
||||
lvx v26,0,r2
|
||||
lis r2,ha16(LV27)
|
||||
la r2,lo16(LV27)(r2)
|
||||
lvx v27,0,r2
|
||||
lis r2,ha16(LV28)
|
||||
la r2,lo16(LV28)(r2)
|
||||
lvx v28,0,r2
|
||||
lis r2,ha16(LV29)
|
||||
la r2,lo16(LV29)(r2)
|
||||
lvx v29,0,r2
|
||||
lis r2,ha16(LV30)
|
||||
la r2,lo16(LV30)(r2)
|
||||
lvx v30,0,r2
|
||||
lis r2,ha16(LV31)
|
||||
la r2,lo16(LV31)(r2)
|
||||
lvx v31,0,r2
|
||||
|
||||
lis r2,0x1234
|
||||
ori r2,r2,0x5678
|
||||
mtocrf 255,r2
|
||||
|
||||
# call test function which will invoke unwinder which "returns" here
|
||||
mtctr r3
|
||||
bctrl
|
||||
|
||||
# verify that non-volatile registers still contain magic values
|
||||
lis r3,0x3333
|
||||
ori r3,r3,0x3131
|
||||
cmpw r3,r31
|
||||
bne L2
|
||||
lis r3,0x3333
|
||||
ori r3,r3,0x3030
|
||||
cmpw r3,r30
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2929
|
||||
cmpw r3,r29
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2828
|
||||
cmpw r3,r28
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2727
|
||||
cmpw r3,r27
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2626
|
||||
cmpw r3,r26
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2525
|
||||
cmpw r3,r25
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2424
|
||||
cmpw r3,r24
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2323
|
||||
cmpw r3,r23
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2222
|
||||
cmpw r3,r22
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2121
|
||||
cmpw r3,r21
|
||||
bne L2
|
||||
lis r3,0x2222
|
||||
ori r3,r3,0x2020
|
||||
cmpw r3,r20
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1919
|
||||
cmpw r3,r19
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1818
|
||||
cmpw r3,r18
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1717
|
||||
cmpw r3,r17
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1616
|
||||
cmpw r3,r16
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1515
|
||||
cmpw r3,r15
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1414
|
||||
cmpw r3,r14
|
||||
bne L2
|
||||
lis r3,0x1111
|
||||
ori r3,r3,0x1313
|
||||
cmpw r3,r13
|
||||
bne L2
|
||||
|
||||
lis r2,ha16(LC14)
|
||||
lfs f1,lo16(LC14)(r2)
|
||||
fcmpu cr7,f1,f14
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC15)
|
||||
lfs f1,lo16(LC15)(r2)
|
||||
fcmpu cr7,f1,f15
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC16)
|
||||
lfs f1,lo16(LC16)(r2)
|
||||
fcmpu cr7,f1,f16
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC17)
|
||||
lfs f1,lo16(LC17)(r2)
|
||||
fcmpu cr7,f1,f17
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC18)
|
||||
lfs f1,lo16(LC18)(r2)
|
||||
fcmpu cr7,f1,f18
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC19)
|
||||
lfs f1,lo16(LC19)(r2)
|
||||
fcmpu cr7,f1,f19
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC20)
|
||||
lfs f1,lo16(LC20)(r2)
|
||||
fcmpu cr7,f1,f20
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC21)
|
||||
lfs f1,lo16(LC21)(r2)
|
||||
fcmpu cr7,f1,f21
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC22)
|
||||
lfs f1,lo16(LC22)(r2)
|
||||
fcmpu cr7,f1,f22
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC23)
|
||||
lfs f1,lo16(LC23)(r2)
|
||||
fcmpu cr7,f1,f23
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC24)
|
||||
lfs f1,lo16(LC24)(r2)
|
||||
fcmpu cr7,f1,f24
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC25)
|
||||
lfs f1,lo16(LC25)(r2)
|
||||
fcmpu cr7,f1,f25
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC26)
|
||||
lfs f1,lo16(LC26)(r2)
|
||||
fcmpu cr7,f1,f26
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC27)
|
||||
lfs f1,lo16(LC27)(r2)
|
||||
fcmpu cr7,f1,f27
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC28)
|
||||
lfs f1,lo16(LC28)(r2)
|
||||
fcmpu cr7,f1,f28
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC29)
|
||||
lfs f1,lo16(LC29)(r2)
|
||||
fcmpu cr7,f1,f29
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC30)
|
||||
lfs f1,lo16(LC30)(r2)
|
||||
fcmpu cr7,f1,f30
|
||||
bne cr7,L2
|
||||
lis r2,ha16(LC31)
|
||||
lfs f1,lo16(LC31)(r2)
|
||||
fcmpu cr7,f1,f31
|
||||
bne cr7,L2
|
||||
|
||||
lis r2,ha16(LV23)
|
||||
la r2,lo16(LV23)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v23
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV24)
|
||||
la r2,lo16(LV24)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v24
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV25)
|
||||
la r2,lo16(LV25)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v25
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV26)
|
||||
la r2,lo16(LV26)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v26
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV27)
|
||||
la r2,lo16(LV27)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v27
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV28)
|
||||
la r2,lo16(LV28)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v28
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV29)
|
||||
la r2,lo16(LV29)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v29
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV30)
|
||||
la r2,lo16(LV30)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v30
|
||||
beq cr6,L2
|
||||
lis r2,ha16(LV31)
|
||||
la r2,lo16(LV31)(r2)
|
||||
lvx v1,0,r2
|
||||
vcmpequw. v0,v1,v31
|
||||
beq cr6,L2
|
||||
|
||||
mfcr r3
|
||||
lis r2,0x00FF
|
||||
ori r2,r2,0xF000
|
||||
and r3,r3,r2
|
||||
lis r2,0x0034
|
||||
ori r2,r2,0x5000
|
||||
cmpw r3,r2
|
||||
bne L2
|
||||
|
||||
li r3,0
|
||||
b L3
|
||||
L2: li r3,1
|
||||
L3:
|
||||
|
||||
addi r1,r1,336
|
||||
lwz r0,8(r1)
|
||||
lmw r13,-220(r1)
|
||||
mtlr r0
|
||||
b restFP ; restore f14-f31
|
||||
LFE2:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
.globl _unwind_tester.eh
|
||||
_unwind_tester.eh:
|
||||
LSFDE27:
|
||||
.set L$set$34,LEFDE27-LASFDE27
|
||||
.long L$set$34 ; FDE Length
|
||||
LASFDE27:
|
||||
.long LASFDE27-EH_frame1 ; FDE CIE offset
|
||||
.long LFB2-. ; FDE initial location
|
||||
.set L$set$35,LFE2-LFB2
|
||||
.long L$set$35 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$36,LCFI43-LFB2
|
||||
.long L$set$36
|
||||
.byte 0x9 ; DW_CFA_register
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$37,LCFI46-LCFI43
|
||||
.long L$set$37
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 0xd0,0x2 ; uleb128 0x150
|
||||
.byte 0x9f ; DW_CFA_offset, column 0x1f
|
||||
.byte 0x25 ; uleb128 0x25
|
||||
.byte 0x9e ; DW_CFA_offset, column 0x1e
|
||||
.byte 0x26 ; uleb128 0x26
|
||||
.byte 0x9d ; DW_CFA_offset, column 0x1d
|
||||
.byte 0x27 ; uleb128 0x27
|
||||
.byte 0x9c ; DW_CFA_offset, column 0x1c
|
||||
.byte 0x28 ; uleb128 0x28
|
||||
.byte 0x9b ; DW_CFA_offset, column 0x1b
|
||||
.byte 0x29 ; uleb128 0x29
|
||||
.byte 0x9a ; DW_CFA_offset, column 0x1a
|
||||
.byte 0x2a ; uleb128 0x2a
|
||||
.byte 0x99 ; DW_CFA_offset, column 0x19
|
||||
.byte 0x2b ; uleb128 0x2b
|
||||
.byte 0x98 ; DW_CFA_offset, column 0x18
|
||||
.byte 0x2c ; uleb128 0x2c
|
||||
.byte 0x97 ; DW_CFA_offset, column 0x17
|
||||
.byte 0x2d ; uleb128 0x2d
|
||||
.byte 0x96 ; DW_CFA_offset, column 0x16
|
||||
.byte 0x2e ; uleb128 0x2e
|
||||
.byte 0x95 ; DW_CFA_offset, column 0x15
|
||||
.byte 0x2f ; uleb128 0x2f
|
||||
.byte 0x94 ; DW_CFA_offset, column 0x14
|
||||
.byte 0x30 ; uleb128 0x30
|
||||
.byte 0x93 ; DW_CFA_offset, column 0x13
|
||||
.byte 0x31 ; uleb128 0x31
|
||||
.byte 0x92 ; DW_CFA_offset, column 0x12
|
||||
.byte 0x32 ; uleb128 0x32
|
||||
.byte 0x91 ; DW_CFA_offset, column 0x11
|
||||
.byte 0x33 ; uleb128 0x33
|
||||
.byte 0x90 ; DW_CFA_offset, column 0x10
|
||||
.byte 0x34 ; uleb128 0x34
|
||||
.byte 0x8f ; DW_CFA_offset, column 0xf
|
||||
.byte 0x35 ; uleb128 0x35
|
||||
.byte 0x8e ; DW_CFA_offset, column 0xe
|
||||
.byte 0x36 ; uleb128 0x36
|
||||
.byte 0x8d ; DW_CFA_offset, column 0xd
|
||||
.byte 0x37 ; uleb128 0x37
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.byte 0xbf ; DW_CFA_offset, column 0x3f
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0xbe ; DW_CFA_offset, column 0x3e
|
||||
.byte 0x4 ; uleb128 0x4
|
||||
.byte 0xbd ; DW_CFA_offset, column 0x3d
|
||||
.byte 0x6 ; uleb128 0x6
|
||||
.byte 0xbc ; DW_CFA_offset, column 0x3c
|
||||
.byte 0x8 ; uleb128 0x8
|
||||
.byte 0xbb ; DW_CFA_offset, column 0x3b
|
||||
.byte 0xa ; uleb128 0xa
|
||||
.byte 0xba ; DW_CFA_offset, column 0x3a
|
||||
.byte 0xc ; uleb128 0xc
|
||||
.byte 0xb9 ; DW_CFA_offset, column 0x39
|
||||
.byte 0xe ; uleb128 0xe
|
||||
.byte 0xb8 ; DW_CFA_offset, column 0x38
|
||||
.byte 0x10 ; uleb128 0x10
|
||||
.byte 0xb7 ; DW_CFA_offset, column 0x37
|
||||
.byte 0x12 ; uleb128 0x12
|
||||
.byte 0xb6 ; DW_CFA_offset, column 0x36
|
||||
.byte 0x14 ; uleb128 0x14
|
||||
.byte 0xb5 ; DW_CFA_offset, column 0x35
|
||||
.byte 0x16 ; uleb128 0x16
|
||||
.byte 0xb4 ; DW_CFA_offset, column 0x34
|
||||
.byte 0x18 ; uleb128 0x18
|
||||
.byte 0xb3 ; DW_CFA_offset, column 0x33
|
||||
.byte 0x1a ; uleb128 0x1a
|
||||
.byte 0xb2 ; DW_CFA_offset, column 0x32
|
||||
.byte 0x1c ; uleb128 0x1c
|
||||
.byte 0xb1 ; DW_CFA_offset, column 0x31
|
||||
.byte 0x1e ; uleb128 0x1e
|
||||
.byte 0xb0 ; DW_CFA_offset, column 0x30
|
||||
.byte 0x20 ; uleb128 0x20
|
||||
.byte 0xaf ; DW_CFA_offset, column 0x2f
|
||||
.byte 0x22 ; uleb128 0x22
|
||||
.byte 0xae ; DW_CFA_offset, column 0x2e
|
||||
.byte 0x24 ; uleb128 0x24
|
||||
.align 2
|
||||
LEFDE27:
|
339
testsuite/unwind_test_ppc_frame.s
Normal file
339
testsuite/unwind_test_ppc_frame.s
Normal file
@ -0,0 +1,339 @@
|
||||
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_ppc.s -arch ppc -fexceptions -faltivec
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_v24_v31
|
||||
.long _test_r29_r31
|
||||
.long _test_f26_f31
|
||||
.long _test_ccr2_ccr4_ctr
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _test_r29_r31
|
||||
_test_r29_r31:
|
||||
LFB11:
|
||||
mflr r0
|
||||
stmw r29,-12(r1)
|
||||
stw r0,8(r1)
|
||||
stwu r1,-80(r1)
|
||||
LCFI10:
|
||||
# trash non-volatile registers
|
||||
li r31,0
|
||||
li r30,0
|
||||
li r29,0
|
||||
# force unwind that should restore non-volatile register
|
||||
bl _uwind_to_main
|
||||
addi r1,r1,80
|
||||
lwz r0,8(r1)
|
||||
lmw r29,-12(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
LFE11:
|
||||
|
||||
|
||||
.text
|
||||
.align 2
|
||||
.globl _test_ccr2_ccr4_ctr
|
||||
_test_ccr2_ccr4_ctr:
|
||||
LFB11a:
|
||||
mflr r0
|
||||
stw r0,8(r1)
|
||||
mfcr r0
|
||||
stw r0,-12(r1)
|
||||
stw r0,-8(r1)
|
||||
mfctr r0
|
||||
stw r0,-4(r1)
|
||||
stwu r1,-80(r1)
|
||||
LCFI10a:
|
||||
# trash non-volatile registers
|
||||
li r3,0
|
||||
mtocrf 40,r3
|
||||
mtctr r3
|
||||
# force unwind that should restore non-volatile register
|
||||
bl _uwind_to_main
|
||||
addi r1,r1,80
|
||||
lwz r0,-4(r1)
|
||||
mtctr r0
|
||||
lwz r0,-8(r1)
|
||||
mtocrf 4,r0
|
||||
lwz r0,-12(r1)
|
||||
mtocrf 128,r0
|
||||
lwz r0,8(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
LFE11a:
|
||||
|
||||
|
||||
.align 2
|
||||
.globl _test_f26_f31
|
||||
_test_f26_f31:
|
||||
LFB4:
|
||||
mflr r0
|
||||
LCFI43:
|
||||
bl saveFP+48 ; save f26-f31
|
||||
LCFI44:
|
||||
stwu r1,-144(r1)
|
||||
LCFI45:
|
||||
# trash non-volatile registers
|
||||
fsub f31,f31,f31
|
||||
fsub f30,f30,f30
|
||||
fsub f29,f29,f29
|
||||
fsub f28,f28,f28
|
||||
fsub f27,f27,f27
|
||||
fsub f26,f26,f26
|
||||
# force unwind that should restore non-volatile register
|
||||
bl _uwind_to_main
|
||||
lwz r0,8(r1)
|
||||
mtlr r0
|
||||
b restFP+48 ; restore f26-f31
|
||||
LFE4:
|
||||
.align 2
|
||||
|
||||
|
||||
.align 2
|
||||
.globl _test_v24_v31
|
||||
_test_v24_v31:
|
||||
LFB3:
|
||||
mflr r0
|
||||
stw r0,8(r1)
|
||||
stwu r1,-352(r1)
|
||||
LCFI2:
|
||||
li r0,208
|
||||
stvx v24,r1,r0
|
||||
li r0,224
|
||||
stvx v25,r1,r0
|
||||
li r0,240
|
||||
stvx v26,r1,r0
|
||||
li r0,256
|
||||
stvx v27,r1,r0
|
||||
li r0,272
|
||||
stvx v28,r1,r0
|
||||
li r0,288
|
||||
stvx v29,r1,r0
|
||||
li r0,304
|
||||
stvx v30,r1,r0
|
||||
li r0,320
|
||||
stvx v31,r1,r0
|
||||
LCFI11:
|
||||
mfspr r0,256
|
||||
stw r0,348(r1)
|
||||
oris r0,r0,0x3ff0
|
||||
ori r0,r0,255
|
||||
mtspr 256,r0
|
||||
|
||||
# trash non-volatile registers
|
||||
vor v24,v20,v20
|
||||
vor v25,v20,v20
|
||||
vor v26,v20,v20
|
||||
vor v27,v20,v20
|
||||
vor v28,v20,v20
|
||||
vor v29,v20,v20
|
||||
vor v30,v20,v20
|
||||
vor v31,v20,v20
|
||||
|
||||
# force unwind that should restore non-volatile register
|
||||
bl _uwind_to_main
|
||||
|
||||
li r0,208
|
||||
lwz r12,348(r1)
|
||||
lvx v24,r1,r0
|
||||
li r0,224
|
||||
lvx v25,r1,r0
|
||||
li r0,240
|
||||
lvx v26,r1,r0
|
||||
li r0,256
|
||||
lvx v27,r1,r0
|
||||
li r0,272
|
||||
lvx v28,r1,r0
|
||||
li r0,288
|
||||
lvx v29,r1,r0
|
||||
li r0,304
|
||||
lvx v30,r1,r0
|
||||
li r0,320
|
||||
lvx v31,r1,r0
|
||||
mtspr 256,r12
|
||||
addi r1,r1,352
|
||||
lwz r0,8(r1)
|
||||
mtlr r0
|
||||
blr
|
||||
LFE3:
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 ; Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 ; CIE Identifier Tag
|
||||
.byte 0x1 ; CIE Version
|
||||
.ascii "zR\0" ; CIE Augmentation
|
||||
.byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
.globl _test_r29_r31.eh
|
||||
_test_r29_r31.eh:
|
||||
LSFDE9:
|
||||
.set L$set$7,LEFDE9-LASFDE9
|
||||
.long L$set$7 ; FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 ; FDE CIE offset
|
||||
.long LFB11-. ; FDE initial location
|
||||
.set L$set$8,LFE11-LFB11
|
||||
.long L$set$8 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$9,LCFI10-LFB11
|
||||
.long L$set$9
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 0x50 ; uleb128 0x50
|
||||
.byte 0x9f ; DW_CFA_offset, column 0x1f
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x9e ; DW_CFA_offset, column 0x1e
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0x9d ; DW_CFA_offset, column 0x1d
|
||||
.byte 0x3 ; uleb128 0x3
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align 2
|
||||
LEFDE9:
|
||||
|
||||
.globl _test_ccr2_ccr4_ctr.eh
|
||||
_test_ccr2_ccr4_ctr.eh:
|
||||
LSFDE9a:
|
||||
.set L$set$7,LEFDE9a-LASFDE9a
|
||||
.long L$set$7 ; FDE Length
|
||||
LASFDE9a:
|
||||
.long LASFDE9a-EH_frame1 ; FDE CIE offset
|
||||
.long LFB11a-. ; FDE initial location
|
||||
.set L$set$8,LFE11a-LFB11a
|
||||
.long L$set$8 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$9,LCFI10a-LFB11a
|
||||
.long L$set$9
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 0x50 ; uleb128 0x50
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x42 ; uleb128 0x42
|
||||
.byte 0x01 ; sleb128 1
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x48 ; uleb128 0x48
|
||||
.byte 0x02 ; sleb128 2
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x46 ; uleb128 0x46
|
||||
.byte 0x03 ; sleb128 3
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align 2
|
||||
LEFDE9a:
|
||||
|
||||
|
||||
|
||||
.globl _test_f26_f31
|
||||
_test_f26_f31.eh:
|
||||
LSFDE29:
|
||||
.set L$set$34,LEFDE29-LASFDE29
|
||||
.long L$set$34 ; FDE Length
|
||||
LASFDE29:
|
||||
.long LASFDE29-EH_frame1 ; FDE CIE offset
|
||||
.long LFB4-. ; FDE initial location
|
||||
.set L$set$35,LFE4-LFB4
|
||||
.long L$set$35 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$36,LCFI43-LFB4
|
||||
.long L$set$36
|
||||
.byte 0x9 ; DW_CFA_register
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$37,LCFI45-LCFI43
|
||||
.long L$set$37
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 0x90,0x1 ; uleb128 0x90
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.byte 0xbf ; DW_CFA_offset, column 0x3f
|
||||
.byte 0x2 ; uleb128 0x2
|
||||
.byte 0xbe ; DW_CFA_offset, column 0x3e
|
||||
.byte 0x4 ; uleb128 0x4
|
||||
.byte 0xbd ; DW_CFA_offset, column 0x3d
|
||||
.byte 0x6 ; uleb128 0x6
|
||||
.byte 0xbc ; DW_CFA_offset, column 0x3c
|
||||
.byte 0x8 ; uleb128 0x8
|
||||
.byte 0xbb ; DW_CFA_offset, column 0x3b
|
||||
.byte 0xa ; uleb128 0xa
|
||||
.byte 0xba ; DW_CFA_offset, column 0x3a
|
||||
.byte 0xc ; uleb128 0xc
|
||||
.align 2
|
||||
LEFDE29:
|
||||
|
||||
|
||||
.globl _test_v24_v31.eh
|
||||
_test_v24_v31.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 ; FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 ; FDE CIE offset
|
||||
.long LFB3-. ; FDE initial location
|
||||
.set L$set$2,LFE3-LFB3
|
||||
.long L$set$2 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI2-LFB3
|
||||
.long L$set$3
|
||||
.byte 0xe ; DW_CFA_def_cfa_offset
|
||||
.byte 0xe0,0x2 ; uleb128 0x160
|
||||
.byte 0x4 ; DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI11-LCFI2
|
||||
.long L$set$4
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x6c ; uleb128 0x6c
|
||||
.byte 0x8 ; uleb128 0x8
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x6b ; uleb128 0x6b
|
||||
.byte 0xc ; uleb128 0xc
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x6a ; uleb128 0x6a
|
||||
.byte 0x10 ; uleb128 0x10
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x69 ; uleb128 0x69
|
||||
.byte 0x14 ; uleb128 0x14
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x68 ; uleb128 0x68
|
||||
.byte 0x18 ; uleb128 0x18
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x67 ; uleb128 0x67
|
||||
.byte 0x1c ; uleb128 0x1c
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x66 ; uleb128 0x66
|
||||
.byte 0x20 ; uleb128 0x20
|
||||
.byte 0x5 ; DW_CFA_offset_extended
|
||||
.byte 0x65 ; uleb128 0x65
|
||||
.byte 0x24 ; uleb128 0x24
|
||||
.byte 0x11 ; DW_CFA_offset_extended_sf
|
||||
.byte 0x41 ; uleb128 0x41
|
||||
.byte 0x7e ; sleb128 -2
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
104
testsuite/unwind_test_x86.s
Normal file
104
testsuite/unwind_test_x86.s
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
#
|
||||
# This is a generic function to test that restoring registers during unwinding work correctly.
|
||||
#
|
||||
|
||||
.text
|
||||
.globl _unwind_tester
|
||||
_unwind_tester:
|
||||
LFB2:
|
||||
pushl %ebp
|
||||
LCFI0:
|
||||
movl %esp, %ebp
|
||||
LCFI1:
|
||||
subl $56, %esp
|
||||
LCFI2:
|
||||
movl %ebx, -12(%ebp)
|
||||
LCFI3:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI4:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI5:
|
||||
# load magic values into non-volatile registers
|
||||
movl $0x12344321, %ebx
|
||||
movl $0x56788765, %esi
|
||||
movl $0xABCDDCBA, %edi
|
||||
# call test function which will invoke unwinder which "returns" here
|
||||
call *8(%ebp)
|
||||
# verify that non-volatile registers still contain magic values
|
||||
cmpl $0x12344321, %ebx
|
||||
jne L2
|
||||
cmpl $0x56788765, %esi
|
||||
jne L2
|
||||
cmpl $0xABCDDCBA, %edi
|
||||
jne L2
|
||||
movl $0, %eax
|
||||
jmp L3
|
||||
L2: movl $1, %eax
|
||||
L3:
|
||||
movl -12(%ebp), %ebx
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE2:
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
.globl _unwind_tester.eh
|
||||
_unwind_tester.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 # FDE CIE offset
|
||||
.long LFB2-. # FDE initial location
|
||||
.set L$set$2,LFE2-LFB2
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI0-LFB2
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI1-LCFI0
|
||||
.long L$set$4
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI5-LCFI1
|
||||
.long L$set$5
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE1:
|
||||
|
||||
|
125
testsuite/unwind_test_x86_64.s
Normal file
125
testsuite/unwind_test_x86_64.s
Normal file
@ -0,0 +1,125 @@
|
||||
|
||||
#
|
||||
# This is a generic function to test that restoring registers during unwinding work correctly.
|
||||
#
|
||||
|
||||
.text
|
||||
.globl _unwind_tester
|
||||
_unwind_tester:
|
||||
LFB3:
|
||||
pushq %rbp
|
||||
LCFI45:
|
||||
movq %rsp, %rbp
|
||||
LCFI46:
|
||||
movq %rbx, -40(%rbp)
|
||||
LCFI47:
|
||||
movq %r12, -32(%rbp)
|
||||
LCFI48:
|
||||
movq %r13, -24(%rbp)
|
||||
LCFI49:
|
||||
movq %r14, -16(%rbp)
|
||||
LCFI50:
|
||||
movq %r15, -8(%rbp)
|
||||
LCFI51:
|
||||
subq $48, %rsp
|
||||
LCFI52:
|
||||
# load magic values into non-volatile registers
|
||||
movq $0x1234567887654321, %rbx
|
||||
movq $0x02468ACEECA86420, %r12
|
||||
movq $0x13579BDFFDB97531, %r13
|
||||
movq $0x1122334455667788, %r14
|
||||
movq $0x0022446688AACCEE, %r15
|
||||
# call test function which will invoke unwinder which "returns" here
|
||||
call *%rdi
|
||||
# verify that non-volatile registers still contain magic values
|
||||
movq $0x1234567887654321, %rax
|
||||
cmpq %rax, %rbx
|
||||
jne L2
|
||||
movq $0x02468ACEECA86420, %rax
|
||||
cmpq %rax, %r12
|
||||
jne L2
|
||||
movq $0x13579BDFFDB97531, %rax
|
||||
cmpq %rax, %r13
|
||||
jne L2
|
||||
movq $0x1122334455667788, %rax
|
||||
cmpq %rax, %r14
|
||||
jne L2
|
||||
movq $0x0022446688AACCEE, %rax
|
||||
cmpq %rax, %r15
|
||||
jne L2
|
||||
movl $0, %eax
|
||||
jmp L3
|
||||
L2: movl $1, %eax
|
||||
L3:
|
||||
movq -40(%rbp), %rbx
|
||||
movq -32(%rbp), %r12
|
||||
movq -24(%rbp), %r13
|
||||
movq -16(%rbp), %r14
|
||||
movq -8(%rbp), %r15
|
||||
leave
|
||||
ret
|
||||
LFE3:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 0x10 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x90 # DW_CFA_offset, column 0x10
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _unwind_tester.eh
|
||||
_unwind_tester.eh:
|
||||
LSFDE23:
|
||||
.set L$set$52,LEFDE23-LASFDE23
|
||||
.long L$set$52 # FDE Length
|
||||
LASFDE23:
|
||||
.long LASFDE23-EH_frame1 # FDE CIE offset
|
||||
.quad LFB3-. # FDE initial location
|
||||
.set L$set$53,LFE3-LFB3
|
||||
.quad L$set$53 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$54,LCFI45-LFB3
|
||||
.long L$set$54
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$55,LCFI46-LCFI45
|
||||
.long L$set$55
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$56,LCFI52-LCFI46
|
||||
.long L$set$56
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.align 3
|
||||
LEFDE23:
|
||||
|
||||
|
||||
|
599
testsuite/unwind_test_x86_64_disable_compact_frame.s
Normal file
599
testsuite/unwind_test_x86_64_disable_compact_frame.s
Normal file
@ -0,0 +1,599 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.quad _test_no_reg
|
||||
.quad _test_rbx
|
||||
.quad _test_rbx_r12
|
||||
.quad _test_rbx_r14
|
||||
.quad _test_rbx_r12_r13
|
||||
.quad _test_rbx_r12_r13_r14
|
||||
.quad _test_r14_r13_r12_rbx
|
||||
.quad _test_rbx_r12_r13_r14_r15
|
||||
.quad _test_r13_rbx_r14_r15_r12
|
||||
.quad 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
LFE14:
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB13:
|
||||
pushq %rbp
|
||||
LCFI2:
|
||||
movq %rsp, %rbp
|
||||
LCFI3:
|
||||
call _uwind_to_main
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_rbx
|
||||
_test_rbx:
|
||||
LFB10:
|
||||
pushq %rbp
|
||||
LCFI8:
|
||||
movq %rsp, %rbp
|
||||
LCFI9:
|
||||
pushq %rbx
|
||||
LCFI10:
|
||||
subq $8, %rsp
|
||||
LCFI11:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
addq $8, %rsp
|
||||
popq %rbx
|
||||
leave
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_rbx_r12
|
||||
_test_rbx_r12:
|
||||
LFB8:
|
||||
pushq %rbp
|
||||
LCFI16:
|
||||
movq %rsp, %rbp
|
||||
LCFI17:
|
||||
movq %rbx, -16(%rbp)
|
||||
LCFI18:
|
||||
movq %r12, -8(%rbp)
|
||||
LCFI19:
|
||||
subq $16, %rsp
|
||||
LCFI20:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
leave
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
.globl _test_rbx_r14
|
||||
_test_rbx_r14:
|
||||
LFB8a:
|
||||
pushq %rbp
|
||||
LCFI16a:
|
||||
movq %rsp, %rbp
|
||||
LCFI17a:
|
||||
movq %rbx, -16(%rbp)
|
||||
LCFI18a:
|
||||
movq %r14, -8(%rbp)
|
||||
LCFI19a:
|
||||
subq $16, %rsp
|
||||
LCFI20a:
|
||||
movq $0, %rbx
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r14
|
||||
leave
|
||||
ret
|
||||
LFE8a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13
|
||||
_test_rbx_r12_r13:
|
||||
LFB6:
|
||||
pushq %rbp
|
||||
LCFI26:
|
||||
movq %rsp, %rbp
|
||||
LCFI27:
|
||||
movq %rbx, -24(%rbp)
|
||||
LCFI28:
|
||||
movq %r12, -16(%rbp)
|
||||
LCFI29:
|
||||
movq %r13, -8(%rbp)
|
||||
LCFI30:
|
||||
subq $32, %rsp
|
||||
LCFI31:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq -24(%rbp), %rbx
|
||||
movq -16(%rbp), %r12
|
||||
movq -8(%rbp), %r13
|
||||
leave
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
.globl _test_rbx_r12_r13_r14
|
||||
_test_rbx_r12_r13_r14:
|
||||
LFB4:
|
||||
pushq %rbp
|
||||
LCFI38:
|
||||
movq %rsp, %rbp
|
||||
LCFI39:
|
||||
movq %rbx, -32(%rbp)
|
||||
LCFI40:
|
||||
movq %r12, -24(%rbp)
|
||||
LCFI41:
|
||||
movq %r13, -16(%rbp)
|
||||
LCFI42:
|
||||
movq %r14, -8(%rbp)
|
||||
LCFI43:
|
||||
subq $32, %rsp
|
||||
LCFI44:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
movq 16(%rsp), %r13
|
||||
movq 24(%rsp), %r14
|
||||
leave
|
||||
ret
|
||||
LFE4:
|
||||
|
||||
.globl _test_r14_r13_r12_rbx
|
||||
_test_r14_r13_r12_rbx:
|
||||
LFB4a:
|
||||
pushq %rbp
|
||||
LCFI38a:
|
||||
movq %rsp, %rbp
|
||||
LCFI39a:
|
||||
movq %r14, -32(%rbp)
|
||||
LCFI40a:
|
||||
movq %r13, -24(%rbp)
|
||||
LCFI41a:
|
||||
movq %r12, -16(%rbp)
|
||||
LCFI42a:
|
||||
movq %rbx, -8(%rbp)
|
||||
LCFI43a:
|
||||
subq $32, %rsp
|
||||
LCFI44a:
|
||||
movq $0, %r14
|
||||
movq $0, %r13
|
||||
movq $0, %r12
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
movq -32(%rbp), %r14
|
||||
movq -24(%rbp), %r13
|
||||
movq -16(%rbp), %r12
|
||||
movq -8(%rbp), %rbx
|
||||
leave
|
||||
ret
|
||||
LFE4a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15
|
||||
_test_rbx_r12_r13_r14_r15:
|
||||
LFB3:
|
||||
pushq %rbp
|
||||
LCFI45:
|
||||
movq %rsp, %rbp
|
||||
LCFI46:
|
||||
movq %rbx, -40(%rbp)
|
||||
LCFI47:
|
||||
movq %r12, -32(%rbp)
|
||||
LCFI48:
|
||||
movq %r13, -24(%rbp)
|
||||
LCFI49:
|
||||
movq %r14, -16(%rbp)
|
||||
LCFI50:
|
||||
movq %r15, -8(%rbp)
|
||||
LCFI51:
|
||||
subq $48, %rsp
|
||||
LCFI52:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq -40(%rbp), %rbx
|
||||
movq -32(%rbp), %r12
|
||||
movq -24(%rbp), %r13
|
||||
movq -16(%rbp), %r14
|
||||
movq -8(%rbp), %r15
|
||||
leave
|
||||
ret
|
||||
LFE3:
|
||||
|
||||
|
||||
.globl _test_r13_rbx_r14_r15_r12
|
||||
_test_r13_rbx_r14_r15_r12:
|
||||
LFB3a:
|
||||
pushq %rbp
|
||||
LCFI45a:
|
||||
movq %rsp, %rbp
|
||||
LCFI46a:
|
||||
movq %r13, -40(%rbp)
|
||||
LCFI47a:
|
||||
movq %rbx, -32(%rbp)
|
||||
LCFI48a:
|
||||
movq %r14, -24(%rbp)
|
||||
LCFI49a:
|
||||
movq %r15, -16(%rbp)
|
||||
LCFI50a:
|
||||
movq %r12, -8(%rbp)
|
||||
LCFI51a:
|
||||
subq $48, %rsp
|
||||
LCFI52a:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq -40(%rbp), %r13
|
||||
movq -32(%rbp), %rbx
|
||||
movq -24(%rbp), %r14
|
||||
movq -16(%rbp), %r15
|
||||
movq -8(%rbp), %r12
|
||||
leave
|
||||
ret
|
||||
LFE3a:
|
||||
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
.ascii "zR\0"
|
||||
.byte 0x1
|
||||
.byte 0x78
|
||||
.byte 0x10
|
||||
.byte 0x1
|
||||
.byte 0x10
|
||||
.byte 0xc
|
||||
.byte 0x7
|
||||
.byte 0x8
|
||||
.byte 0x90 // DW_CFA_offset(ret_addr, -8)
|
||||
.byte 0x1
|
||||
.byte 0x90 // DW_CFA_offset(ret_addr, -8)
|
||||
.byte 0x1 // this repeat is idiom that means don't create compact unwind info
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE3:
|
||||
.set L$set$5,LEFDE3-LASFDE3
|
||||
.long L$set$5
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1
|
||||
.quad LFB13-.
|
||||
.set L$set$6,LFE13-LFB13
|
||||
.quad L$set$6
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$7,LCFI2-LFB13
|
||||
.long L$set$7
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$8,LCFI3-LCFI2
|
||||
.long L$set$8
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.align 3
|
||||
LEFDE3:
|
||||
|
||||
.globl _test_rbx.eh
|
||||
_test_rbx.eh:
|
||||
LSFDE9:
|
||||
.set L$set$17,LEFDE9-LASFDE9
|
||||
.long L$set$17
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1
|
||||
.quad LFB10-.
|
||||
.set L$set$18,LFE10-LFB10
|
||||
.quad L$set$18
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$19,LCFI8-LFB10
|
||||
.long L$set$19
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$20,LCFI9-LCFI8
|
||||
.long L$set$20
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$21,LCFI11-LCFI9
|
||||
.long L$set$21
|
||||
.byte 0x83
|
||||
.byte 0x3
|
||||
.align 3
|
||||
LEFDE9:
|
||||
|
||||
.globl _test_rbx_r12.eh
|
||||
_test_rbx_r12.eh:
|
||||
LSFDE13:
|
||||
.set L$set$27,LEFDE13-LASFDE13
|
||||
.long L$set$27
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1
|
||||
.quad LFB8-.
|
||||
.set L$set$28,LFE8-LFB8
|
||||
.quad L$set$28
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$29,LCFI16-LFB8
|
||||
.long L$set$29
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$30,LCFI17-LCFI16
|
||||
.long L$set$30
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$31,LCFI20-LCFI17
|
||||
.long L$set$31
|
||||
.byte 0x8c
|
||||
.byte 0x3
|
||||
.byte 0x83
|
||||
.byte 0x4
|
||||
.align 3
|
||||
LEFDE13:
|
||||
|
||||
.globl _test_rbx_r14.eh
|
||||
_test_rbx_r14.eh:
|
||||
LSFDE13a:
|
||||
.set L$set$27a,LEFDE13a-LASFDE13a
|
||||
.long L$set$27a
|
||||
LASFDE13a:
|
||||
.long LASFDE13a-EH_frame1
|
||||
.quad LFB8a-.
|
||||
.set L$set$28a,LFE8a-LFB8a
|
||||
.quad L$set$28a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$29a,LCFI16a-LFB8a
|
||||
.long L$set$29a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$30a,LCFI17a-LCFI16a
|
||||
.long L$set$30a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$31a,LCFI20a-LCFI17a
|
||||
.long L$set$31a
|
||||
.byte 0x8e
|
||||
.byte 0x3
|
||||
.byte 0x83
|
||||
.byte 0x4
|
||||
.align 3
|
||||
LEFDE13a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13.eh
|
||||
_test_rbx_r12_r13.eh:
|
||||
LSFDE17:
|
||||
.set L$set$37,LEFDE17-LASFDE17
|
||||
.long L$set$37
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1
|
||||
.quad LFB6-.
|
||||
.set L$set$38,LFE6-LFB6
|
||||
.quad L$set$38
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$39,LCFI26-LFB6
|
||||
.long L$set$39
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$40,LCFI27-LCFI26
|
||||
.long L$set$40
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$41,LCFI31-LCFI27
|
||||
.long L$set$41
|
||||
.byte 0x8d
|
||||
.byte 0x3
|
||||
.byte 0x8c
|
||||
.byte 0x4
|
||||
.byte 0x83
|
||||
.byte 0x5
|
||||
.align 3
|
||||
LEFDE17:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14.eh
|
||||
_test_rbx_r12_r13_r14.eh:
|
||||
LSFDE21:
|
||||
.set L$set$47,LEFDE21-LASFDE21
|
||||
.long L$set$47
|
||||
LASFDE21:
|
||||
.long LASFDE21-EH_frame1
|
||||
.quad LFB4-.
|
||||
.set L$set$48,LFE4-LFB4
|
||||
.quad L$set$48
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$49,LCFI38-LFB4
|
||||
.long L$set$49
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$50,LCFI39-LCFI38
|
||||
.long L$set$50
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$51,LCFI44-LCFI39
|
||||
.long L$set$51
|
||||
.byte 0x8e
|
||||
.byte 0x3
|
||||
.byte 0x8d
|
||||
.byte 0x4
|
||||
.byte 0x8c
|
||||
.byte 0x5
|
||||
.byte 0x83
|
||||
.byte 0x6
|
||||
.align 3
|
||||
LEFDE21:
|
||||
|
||||
.globl _test_r14_r13_r12_rbx.eh
|
||||
_test_r14_r13_r12_rbx.eh:
|
||||
LSFDE21a:
|
||||
.set L$set$47a,LEFDE21a-LASFDE21a
|
||||
.long L$set$47a
|
||||
LASFDE21a:
|
||||
.long LASFDE21a-EH_frame1
|
||||
.quad LFB4a-.
|
||||
.set L$set$48a,LFE4a-LFB4a
|
||||
.quad L$set$48a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$49a,LCFI38a-LFB4a
|
||||
.long L$set$49a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$50a,LCFI39a-LCFI38a
|
||||
.long L$set$50a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$51a,LCFI44a-LCFI39a
|
||||
.long L$set$51a
|
||||
.byte 0x8e
|
||||
.byte 0x6
|
||||
.byte 0x8d
|
||||
.byte 0x5
|
||||
.byte 0x8c
|
||||
.byte 0x4
|
||||
.byte 0x83
|
||||
.byte 0x3
|
||||
.align 3
|
||||
LEFDE21a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15.eh
|
||||
_test_rbx_r12_r13_r14_r15.eh:
|
||||
LSFDE23:
|
||||
.set L$set$52,LEFDE23-LASFDE23
|
||||
.long L$set$52
|
||||
LASFDE23:
|
||||
.long LASFDE23-EH_frame1
|
||||
.quad LFB3-.
|
||||
.set L$set$53,LFE3-LFB3
|
||||
.quad L$set$53
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$54,LCFI45-LFB3
|
||||
.long L$set$54
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$55,LCFI46-LCFI45
|
||||
.long L$set$55
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$56,LCFI52-LCFI46
|
||||
.long L$set$56
|
||||
.byte 0x8f
|
||||
.byte 0x3
|
||||
.byte 0x8e
|
||||
.byte 0x4
|
||||
.byte 0x8d
|
||||
.byte 0x5
|
||||
.byte 0x8c
|
||||
.byte 0x6
|
||||
.byte 0x83
|
||||
.byte 0x7
|
||||
.align 3
|
||||
LEFDE23:
|
||||
|
||||
|
||||
.globl _test_r13_rbx_r14_r15_r12.eh
|
||||
_test_r13_rbx_r14_r15_r12.eh:
|
||||
LSFDE23a:
|
||||
.set L$set$52a,LEFDE23a-LASFDE23a
|
||||
.long L$set$52a
|
||||
LASFDE23a:
|
||||
.long LASFDE23a-EH_frame1
|
||||
.quad LFB3a-.
|
||||
.set L$set$53a,LFE3a-LFB3a
|
||||
.quad L$set$53a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$54a,LCFI45a-LFB3a
|
||||
.long L$set$54a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$55a,LCFI46a-LCFI45a
|
||||
.long L$set$55a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$56a,LCFI52a-LCFI46a
|
||||
.long L$set$56a
|
||||
.byte 0x8c
|
||||
.byte 0x3
|
||||
.byte 0x8f
|
||||
.byte 0x4
|
||||
.byte 0x8e
|
||||
.byte 0x5
|
||||
.byte 0x83
|
||||
.byte 0x6
|
||||
.byte 0x8d
|
||||
.byte 0x7
|
||||
.align 3
|
||||
LEFDE23a:
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
674
testsuite/unwind_test_x86_64_frame.s
Normal file
674
testsuite/unwind_test_x86_64_frame.s
Normal file
@ -0,0 +1,674 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -DUSE_COMPACT_UNWIND=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -DUSE_EH_FRAME=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -DUSE_COMPACT_UNWIND=1 -DUSE_EH_FRAME=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -DUSE_EH_FRAME=1 -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.quad _test_no_reg
|
||||
.quad _test_rbx
|
||||
.quad _test_rbx_r12
|
||||
.quad _test_rbx_r14
|
||||
.quad _test_rbx_r12_r13
|
||||
.quad _test_rbx_r12_r13_r14
|
||||
.quad _test_r14_r13_r12_rbx
|
||||
.quad _test_rbx_r12_r13_r14_r15
|
||||
.quad _test_r13_rbx_r14_r15_r12
|
||||
.quad 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
LFE14:
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB13:
|
||||
pushq %rbp
|
||||
LCFI2:
|
||||
movq %rsp, %rbp
|
||||
LCFI3:
|
||||
call _uwind_to_main
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_rbx
|
||||
_test_rbx:
|
||||
LFB10:
|
||||
pushq %rbp
|
||||
LCFI8:
|
||||
movq %rsp, %rbp
|
||||
LCFI9:
|
||||
pushq %rbx
|
||||
LCFI10:
|
||||
subq $8, %rsp
|
||||
LCFI11:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
addq $8, %rsp
|
||||
popq %rbx
|
||||
leave
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_rbx_r12
|
||||
_test_rbx_r12:
|
||||
LFB8:
|
||||
pushq %rbp
|
||||
LCFI16:
|
||||
movq %rsp, %rbp
|
||||
LCFI17:
|
||||
movq %rbx, -16(%rbp)
|
||||
LCFI18:
|
||||
movq %r12, -8(%rbp)
|
||||
LCFI19:
|
||||
subq $16, %rsp
|
||||
LCFI20:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
leave
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
.globl _test_rbx_r14
|
||||
_test_rbx_r14:
|
||||
LFB8a:
|
||||
pushq %rbp
|
||||
LCFI16a:
|
||||
movq %rsp, %rbp
|
||||
LCFI17a:
|
||||
movq %rbx, -16(%rbp)
|
||||
LCFI18a:
|
||||
movq %r14, -8(%rbp)
|
||||
LCFI19a:
|
||||
subq $16, %rsp
|
||||
LCFI20a:
|
||||
movq $0, %rbx
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r14
|
||||
leave
|
||||
ret
|
||||
LFE8a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13
|
||||
_test_rbx_r12_r13:
|
||||
LFB6:
|
||||
pushq %rbp
|
||||
LCFI26:
|
||||
movq %rsp, %rbp
|
||||
LCFI27:
|
||||
movq %rbx, -24(%rbp)
|
||||
LCFI28:
|
||||
movq %r12, -16(%rbp)
|
||||
LCFI29:
|
||||
movq %r13, -8(%rbp)
|
||||
LCFI30:
|
||||
subq $32, %rsp
|
||||
LCFI31:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq -24(%rbp), %rbx
|
||||
movq -16(%rbp), %r12
|
||||
movq -8(%rbp), %r13
|
||||
leave
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
.globl _test_rbx_r12_r13_r14
|
||||
_test_rbx_r12_r13_r14:
|
||||
LFB4:
|
||||
pushq %rbp
|
||||
LCFI38:
|
||||
movq %rsp, %rbp
|
||||
LCFI39:
|
||||
movq %rbx, -32(%rbp)
|
||||
LCFI40:
|
||||
movq %r12, -24(%rbp)
|
||||
LCFI41:
|
||||
movq %r13, -16(%rbp)
|
||||
LCFI42:
|
||||
movq %r14, -8(%rbp)
|
||||
LCFI43:
|
||||
subq $32, %rsp
|
||||
LCFI44:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
movq 16(%rsp), %r13
|
||||
movq 24(%rsp), %r14
|
||||
leave
|
||||
ret
|
||||
LFE4:
|
||||
|
||||
.globl _test_r14_r13_r12_rbx
|
||||
_test_r14_r13_r12_rbx:
|
||||
LFB4a:
|
||||
pushq %rbp
|
||||
LCFI38a:
|
||||
movq %rsp, %rbp
|
||||
LCFI39a:
|
||||
movq %r14, -32(%rbp)
|
||||
LCFI40a:
|
||||
movq %r13, -24(%rbp)
|
||||
LCFI41a:
|
||||
movq %r12, -16(%rbp)
|
||||
LCFI42a:
|
||||
movq %rbx, -8(%rbp)
|
||||
LCFI43a:
|
||||
subq $32, %rsp
|
||||
LCFI44a:
|
||||
movq $0, %r14
|
||||
movq $0, %r13
|
||||
movq $0, %r12
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
movq -32(%rbp), %r14
|
||||
movq -24(%rbp), %r13
|
||||
movq -16(%rbp), %r12
|
||||
movq -8(%rbp), %rbx
|
||||
leave
|
||||
ret
|
||||
LFE4a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15
|
||||
_test_rbx_r12_r13_r14_r15:
|
||||
LFB3:
|
||||
pushq %rbp
|
||||
LCFI45:
|
||||
movq %rsp, %rbp
|
||||
LCFI46:
|
||||
movq %rbx, -40(%rbp)
|
||||
LCFI47:
|
||||
movq %r12, -32(%rbp)
|
||||
LCFI48:
|
||||
movq %r13, -24(%rbp)
|
||||
LCFI49:
|
||||
movq %r14, -16(%rbp)
|
||||
LCFI50:
|
||||
movq %r15, -8(%rbp)
|
||||
LCFI51:
|
||||
subq $48, %rsp
|
||||
LCFI52:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq -40(%rbp), %rbx
|
||||
movq -32(%rbp), %r12
|
||||
movq -24(%rbp), %r13
|
||||
movq -16(%rbp), %r14
|
||||
movq -8(%rbp), %r15
|
||||
leave
|
||||
ret
|
||||
LFE3:
|
||||
|
||||
|
||||
.globl _test_r13_rbx_r14_r15_r12
|
||||
_test_r13_rbx_r14_r15_r12:
|
||||
LFB3a:
|
||||
pushq %rbp
|
||||
LCFI45a:
|
||||
movq %rsp, %rbp
|
||||
LCFI46a:
|
||||
movq %r13, -40(%rbp)
|
||||
LCFI47a:
|
||||
movq %rbx, -32(%rbp)
|
||||
LCFI48a:
|
||||
movq %r14, -24(%rbp)
|
||||
LCFI49a:
|
||||
movq %r15, -16(%rbp)
|
||||
LCFI50a:
|
||||
movq %r12, -8(%rbp)
|
||||
LCFI51a:
|
||||
subq $48, %rsp
|
||||
LCFI52a:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq -40(%rbp), %r13
|
||||
movq -32(%rbp), %rbx
|
||||
movq -24(%rbp), %r14
|
||||
movq -16(%rbp), %r15
|
||||
movq -8(%rbp), %r12
|
||||
leave
|
||||
ret
|
||||
LFE3a:
|
||||
|
||||
|
||||
|
||||
#if USE_EH_FRAME
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
.ascii "zR\0"
|
||||
.byte 0x1
|
||||
.byte 0x78
|
||||
.byte 0x10
|
||||
.byte 0x1
|
||||
.byte 0x10
|
||||
.byte 0xc
|
||||
.byte 0x7
|
||||
.byte 0x8
|
||||
.byte 0x90
|
||||
.byte 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE3:
|
||||
.set L$set$5,LEFDE3-LASFDE3
|
||||
.long L$set$5
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1
|
||||
.quad LFB13-.
|
||||
.set L$set$6,LFE13-LFB13
|
||||
.quad L$set$6
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$7,LCFI2-LFB13
|
||||
.long L$set$7
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$8,LCFI3-LCFI2
|
||||
.long L$set$8
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.align 3
|
||||
LEFDE3:
|
||||
|
||||
.globl _test_rbx.eh
|
||||
_test_rbx.eh:
|
||||
LSFDE9:
|
||||
.set L$set$17,LEFDE9-LASFDE9
|
||||
.long L$set$17
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1
|
||||
.quad LFB10-.
|
||||
.set L$set$18,LFE10-LFB10
|
||||
.quad L$set$18
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$19,LCFI8-LFB10
|
||||
.long L$set$19
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$20,LCFI9-LCFI8
|
||||
.long L$set$20
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$21,LCFI11-LCFI9
|
||||
.long L$set$21
|
||||
.byte 0x83
|
||||
.byte 0x3
|
||||
.align 3
|
||||
LEFDE9:
|
||||
|
||||
.globl _test_rbx_r12.eh
|
||||
_test_rbx_r12.eh:
|
||||
LSFDE13:
|
||||
.set L$set$27,LEFDE13-LASFDE13
|
||||
.long L$set$27
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1
|
||||
.quad LFB8-.
|
||||
.set L$set$28,LFE8-LFB8
|
||||
.quad L$set$28
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$29,LCFI16-LFB8
|
||||
.long L$set$29
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$30,LCFI17-LCFI16
|
||||
.long L$set$30
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$31,LCFI20-LCFI17
|
||||
.long L$set$31
|
||||
.byte 0x8c
|
||||
.byte 0x3
|
||||
.byte 0x83
|
||||
.byte 0x4
|
||||
.align 3
|
||||
LEFDE13:
|
||||
|
||||
.globl _test_rbx_r14.eh
|
||||
_test_rbx_r14.eh:
|
||||
LSFDE13a:
|
||||
.set L$set$27a,LEFDE13a-LASFDE13a
|
||||
.long L$set$27a
|
||||
LASFDE13a:
|
||||
.long LASFDE13a-EH_frame1
|
||||
.quad LFB8a-.
|
||||
.set L$set$28a,LFE8a-LFB8a
|
||||
.quad L$set$28a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$29a,LCFI16a-LFB8a
|
||||
.long L$set$29a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$30a,LCFI17a-LCFI16a
|
||||
.long L$set$30a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$31a,LCFI20a-LCFI17a
|
||||
.long L$set$31a
|
||||
.byte 0x8e
|
||||
.byte 0x3
|
||||
.byte 0x83
|
||||
.byte 0x4
|
||||
.align 3
|
||||
LEFDE13a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13.eh
|
||||
_test_rbx_r12_r13.eh:
|
||||
LSFDE17:
|
||||
.set L$set$37,LEFDE17-LASFDE17
|
||||
.long L$set$37
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1
|
||||
.quad LFB6-.
|
||||
.set L$set$38,LFE6-LFB6
|
||||
.quad L$set$38
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$39,LCFI26-LFB6
|
||||
.long L$set$39
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$40,LCFI27-LCFI26
|
||||
.long L$set$40
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$41,LCFI31-LCFI27
|
||||
.long L$set$41
|
||||
.byte 0x8d
|
||||
.byte 0x3
|
||||
.byte 0x8c
|
||||
.byte 0x4
|
||||
.byte 0x83
|
||||
.byte 0x5
|
||||
.align 3
|
||||
LEFDE17:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14.eh
|
||||
_test_rbx_r12_r13_r14.eh:
|
||||
LSFDE21:
|
||||
.set L$set$47,LEFDE21-LASFDE21
|
||||
.long L$set$47
|
||||
LASFDE21:
|
||||
.long LASFDE21-EH_frame1
|
||||
.quad LFB4-.
|
||||
.set L$set$48,LFE4-LFB4
|
||||
.quad L$set$48
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$49,LCFI38-LFB4
|
||||
.long L$set$49
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$50,LCFI39-LCFI38
|
||||
.long L$set$50
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$51,LCFI44-LCFI39
|
||||
.long L$set$51
|
||||
.byte 0x8e
|
||||
.byte 0x3
|
||||
.byte 0x8d
|
||||
.byte 0x4
|
||||
.byte 0x8c
|
||||
.byte 0x5
|
||||
.byte 0x83
|
||||
.byte 0x6
|
||||
.align 3
|
||||
LEFDE21:
|
||||
|
||||
.globl _test_r14_r13_r12_rbx.eh
|
||||
_test_r14_r13_r12_rbx.eh:
|
||||
LSFDE21a:
|
||||
.set L$set$47a,LEFDE21a-LASFDE21a
|
||||
.long L$set$47a
|
||||
LASFDE21a:
|
||||
.long LASFDE21a-EH_frame1
|
||||
.quad LFB4a-.
|
||||
.set L$set$48a,LFE4a-LFB4a
|
||||
.quad L$set$48a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$49a,LCFI38a-LFB4a
|
||||
.long L$set$49a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$50a,LCFI39a-LCFI38a
|
||||
.long L$set$50a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$51a,LCFI44a-LCFI39a
|
||||
.long L$set$51a
|
||||
.byte 0x8e
|
||||
.byte 0x6
|
||||
.byte 0x8d
|
||||
.byte 0x5
|
||||
.byte 0x8c
|
||||
.byte 0x4
|
||||
.byte 0x83
|
||||
.byte 0x3
|
||||
.align 3
|
||||
LEFDE21a:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15.eh
|
||||
_test_rbx_r12_r13_r14_r15.eh:
|
||||
LSFDE23:
|
||||
.set L$set$52,LEFDE23-LASFDE23
|
||||
.long L$set$52
|
||||
LASFDE23:
|
||||
.long LASFDE23-EH_frame1
|
||||
.quad LFB3-.
|
||||
.set L$set$53,LFE3-LFB3
|
||||
.quad L$set$53
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$54,LCFI45-LFB3
|
||||
.long L$set$54
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$55,LCFI46-LCFI45
|
||||
.long L$set$55
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$56,LCFI52-LCFI46
|
||||
.long L$set$56
|
||||
.byte 0x8f
|
||||
.byte 0x3
|
||||
.byte 0x8e
|
||||
.byte 0x4
|
||||
.byte 0x8d
|
||||
.byte 0x5
|
||||
.byte 0x8c
|
||||
.byte 0x6
|
||||
.byte 0x83
|
||||
.byte 0x7
|
||||
.align 3
|
||||
LEFDE23:
|
||||
|
||||
|
||||
.globl _test_r13_rbx_r14_r15_r12.eh
|
||||
_test_r13_rbx_r14_r15_r12.eh:
|
||||
LSFDE23a:
|
||||
.set L$set$52a,LEFDE23a-LASFDE23a
|
||||
.long L$set$52a
|
||||
LASFDE23a:
|
||||
.long LASFDE23a-EH_frame1
|
||||
.quad LFB3a-.
|
||||
.set L$set$53a,LFE3a-LFB3a
|
||||
.quad L$set$53a
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$54a,LCFI45a-LFB3a
|
||||
.long L$set$54a
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$55a,LCFI46a-LCFI45a
|
||||
.long L$set$55a
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$56a,LCFI52a-LCFI46a
|
||||
.long L$set$56a
|
||||
.byte 0x8c
|
||||
.byte 0x3
|
||||
.byte 0x8f
|
||||
.byte 0x4
|
||||
.byte 0x8e
|
||||
.byte 0x5
|
||||
.byte 0x83
|
||||
.byte 0x6
|
||||
.byte 0x8d
|
||||
.byte 0x7
|
||||
.align 3
|
||||
LEFDE23a:
|
||||
#endif // USE_EH_FRAME
|
||||
|
||||
|
||||
|
||||
#if USE_COMPACT_UNWIND
|
||||
|
||||
.section __LD,__compact_unwind,regular,debug
|
||||
|
||||
.quad _test_no_reg
|
||||
.set L101,LFE13-_test_no_reg
|
||||
.long L101
|
||||
.long 0x01000000
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx
|
||||
.set L102,LFE10-_test_rbx
|
||||
.long L102
|
||||
.long 0x01010001
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx_r12
|
||||
.set L103,LFE8-_test_rbx_r12
|
||||
.long L103
|
||||
.long 0x01020011
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx_r14
|
||||
.set L104,LFE8a-_test_rbx_r14
|
||||
.long L104
|
||||
.long 0x01020021
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx_r12_r13
|
||||
.set L105,LFE6-_test_rbx_r12_r13
|
||||
.long L105
|
||||
.long 0x010300D1
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx_r12_r13_r14
|
||||
.set L106,LFE4-_test_rbx_r12_r13_r14
|
||||
.long L106
|
||||
.long 0x010408D1
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_r14_r13_r12_rbx
|
||||
.set L107,LFE4a-_test_r14_r13_r12_rbx
|
||||
.long L107
|
||||
.long 0x0104029C
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_rbx_r12_r13_r14_r15
|
||||
.set L108,LFE3-_test_rbx_r12_r13_r14_r15
|
||||
.long L108
|
||||
.long 0x010558D1
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
.quad _test_r13_rbx_r14_r15_r12
|
||||
.set L109,LFE3a-_test_r13_rbx_r14_r15_r12
|
||||
.long L109
|
||||
.long 0x01052B0B
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
#endif // USE_COMPACT_UNWIND
|
||||
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
583
testsuite/unwind_test_x86_64_frameless.s
Normal file
583
testsuite/unwind_test_x86_64_frameless.s
Normal file
@ -0,0 +1,583 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -Wl,-no_compact_unwind
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.quad _test_no_reg
|
||||
.quad _test_rbx
|
||||
.quad _test_rbx_r12
|
||||
.quad _test_rbx_r12_r13
|
||||
.quad _test_rbx_r12_r13_r14
|
||||
.quad _test_rbx_r12_r13_r14_r15
|
||||
.quad _test_rbx_rbp
|
||||
.quad _test_rbx_rbp_r12
|
||||
.quad _test_rbx_rbp_r12_r13
|
||||
.quad _test_rbx_rbp_r12_r13_r14
|
||||
.quad _test_rbx_rbp_r12_r13_r14_r15
|
||||
.quad 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB13:
|
||||
subq $8, %rsp
|
||||
LCFI0:
|
||||
call _uwind_to_main
|
||||
addq $8, %rsp
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_rbx
|
||||
_test_rbx:
|
||||
LFB10:
|
||||
pushq %rbx
|
||||
LCFI3:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
popq %rbx
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_rbx_r12
|
||||
_test_rbx_r12:
|
||||
LFB8:
|
||||
movq %rbx, -16(%rsp)
|
||||
LCFI5:
|
||||
movq %r12, -8(%rsp)
|
||||
LCFI6:
|
||||
subq $24, %rsp
|
||||
LCFI7:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq 8(%rsp), %rbx
|
||||
movq 16(%rsp), %r12
|
||||
addq $24, %rsp
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp
|
||||
_test_rbx_rbp:
|
||||
LFB7:
|
||||
movq %rbx, -16(%rsp)
|
||||
LCFI8:
|
||||
movq %rbp, -8(%rsp)
|
||||
LCFI9:
|
||||
subq $24, %rsp
|
||||
LCFI10:
|
||||
movq $0, %rbp
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
movq 8(%rsp), %rbx
|
||||
movq 16(%rsp), %rbp
|
||||
addq $24, %rsp
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13
|
||||
_test_rbx_r12_r13:
|
||||
LFB6:
|
||||
movq %rbx, -24(%rsp)
|
||||
LCFI11:
|
||||
movq %r12, -16(%rsp)
|
||||
LCFI12:
|
||||
movq %r13, -8(%rsp)
|
||||
LCFI13:
|
||||
subq $24, %rsp
|
||||
LCFI14:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
movq 16(%rsp), %r13
|
||||
addq $24, %rsp
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14
|
||||
_test_rbx_r12_r13_r14:
|
||||
LFB4:
|
||||
movq %rbx, -32(%rsp)
|
||||
LCFI19:
|
||||
movq %r12, -24(%rsp)
|
||||
LCFI20:
|
||||
movq %r13, -16(%rsp)
|
||||
LCFI21:
|
||||
movq %r14, -8(%rsp)
|
||||
LCFI22:
|
||||
subq $40, %rsp
|
||||
LCFI23:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq 8(%rsp), %rbx
|
||||
movq 16(%rsp), %r12
|
||||
movq 24(%rsp), %r13
|
||||
movq 32(%rsp), %r14
|
||||
addq $40, %rsp
|
||||
ret
|
||||
LFE4:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15
|
||||
_test_rbx_r12_r13_r14_r15:
|
||||
LFB3:
|
||||
movq %rbx, -40(%rsp)
|
||||
LCFI24:
|
||||
movq %r12, -32(%rsp)
|
||||
LCFI25:
|
||||
movq %r13, -24(%rsp)
|
||||
LCFI26:
|
||||
movq %r14, -16(%rsp)
|
||||
LCFI27:
|
||||
movq %r15, -8(%rsp)
|
||||
LCFI28:
|
||||
subq $40, %rsp
|
||||
LCFI29:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
movq 16(%rsp), %r13
|
||||
movq 24(%rsp), %r14
|
||||
movq 32(%rsp), %r15
|
||||
addq $40, %rsp
|
||||
ret
|
||||
LFE3:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14_r15
|
||||
_test_rbx_rbp_r12_r13_r14_r15:
|
||||
LFB2:
|
||||
movq %rbx, -48(%rsp)
|
||||
LCFI30:
|
||||
movq %rbp, -40(%rsp)
|
||||
LCFI31:
|
||||
movq %r12, -32(%rsp)
|
||||
LCFI32:
|
||||
movq %r13, -24(%rsp)
|
||||
LCFI33:
|
||||
movq %r14, -16(%rsp)
|
||||
LCFI34:
|
||||
movq %r15, -8(%rsp)
|
||||
LCFI35:
|
||||
subq $72, %rsp
|
||||
LCFI36:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq 24(%rsp), %rbx
|
||||
movq 32(%rsp), %rbp
|
||||
movq 40(%rsp), %r12
|
||||
movq 48(%rsp), %r13
|
||||
movq 56(%rsp), %r14
|
||||
movq 64(%rsp), %r15
|
||||
addq $72, %rsp
|
||||
ret
|
||||
LFE2:
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12
|
||||
_test_rbx_rbp_r12:
|
||||
LFB11:
|
||||
movq %rbx, -24(%rsp)
|
||||
movq %rbp, -16(%rsp)
|
||||
movq %r12, -8(%rsp)
|
||||
subq $24, %rsp
|
||||
LCFI11a:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %rbp
|
||||
movq 16(%rsp), %r12
|
||||
addq $24, %rsp
|
||||
ret
|
||||
LFE11:
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13
|
||||
_test_rbx_rbp_r12_r13:
|
||||
LFB457:
|
||||
movq %rbx, -32(%rsp)
|
||||
movq %rbp, -24(%rsp)
|
||||
movq %r12, -16(%rsp)
|
||||
movq %r13, -8(%rsp)
|
||||
subq $40, %rsp
|
||||
LFB457a:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq 8(%rsp), %rbx
|
||||
movq 16(%rsp), %rbp
|
||||
movq 24(%rsp), %r12
|
||||
movq 32(%rsp), %r13
|
||||
addq $40, %rsp
|
||||
ret
|
||||
LFE457:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14
|
||||
_test_rbx_rbp_r12_r13_r14:
|
||||
LFB17:
|
||||
movq %rbx, -40(%rsp)
|
||||
movq %rbp, -32(%rsp)
|
||||
movq %r12, -24(%rsp)
|
||||
movq %r13, -16(%rsp)
|
||||
movq %r14, -8(%rsp)
|
||||
subq $40, %rsp
|
||||
LFB17a:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %rbp
|
||||
movq 16(%rsp), %r12
|
||||
movq 24(%rsp), %r13
|
||||
movq 32(%rsp), %r14
|
||||
addq $40, %rsp
|
||||
ret
|
||||
LFE17:
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 0x10 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x90 # DW_CFA_offset, column 0x10
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE3:
|
||||
.set L$set$3,LEFDE3-LASFDE3
|
||||
.long L$set$3 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.quad LFB13-. # FDE initial location
|
||||
.set L$set$4,LFE13-LFB13
|
||||
.quad L$set$4 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI0-LFB13
|
||||
.long L$set$5
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.align 3
|
||||
LEFDE3:
|
||||
|
||||
.globl _test_rbx.eh
|
||||
_test_rbx.eh:
|
||||
LSFDE9:
|
||||
.set L$set$12,LEFDE9-LASFDE9
|
||||
.long L$set$12 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.quad LFB10-. # FDE initial location
|
||||
.set L$set$13,LFE10-LFB10
|
||||
.quad L$set$13 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14,LCFI3-LFB10
|
||||
.long L$set$14
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 3
|
||||
LEFDE9:
|
||||
|
||||
.globl _test_rbx_r12.eh
|
||||
_test_rbx_r12.eh:
|
||||
LSFDE13:
|
||||
.set L$set$18,LEFDE13-LASFDE13
|
||||
.long L$set$18 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.quad LFB8-. # FDE initial location
|
||||
.set L$set$19,LFE8-LFB8
|
||||
.quad L$set$19 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$20,LCFI7-LFB8
|
||||
.long L$set$20
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE13:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp.eh
|
||||
_test_rbx_rbp.eh:
|
||||
LSFDE14:
|
||||
.set L$set$21,LEFDE14-LASFDE14
|
||||
.long L$set$21 # FDE Length
|
||||
LASFDE14:
|
||||
.long LASFDE14-EH_frame1 # FDE CIE offset
|
||||
.quad LFB7-. # FDE initial location
|
||||
.set L$set$22,LFE7-LFB7
|
||||
.quad L$set$22 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI10-LFB7
|
||||
.long L$set$23
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE14:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13.eh
|
||||
_test_rbx_r12_r13.eh:
|
||||
LSFDE17:
|
||||
.set L$set$24,LEFDE17-LASFDE17
|
||||
.long L$set$24 # FDE Length
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1 # FDE CIE offset
|
||||
.quad LFB6-. # FDE initial location
|
||||
.set L$set$25,LFE6-LFB6
|
||||
.quad L$set$25 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$26,LCFI14-LFB6
|
||||
.long L$set$26
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 3
|
||||
LEFDE17:
|
||||
|
||||
.globl _test_rbx_r12_r13_r14.eh
|
||||
_test_rbx_r12_r13_r14.eh:
|
||||
LSFDE21:
|
||||
.set L$set$30,LEFDE21-LASFDE21
|
||||
.long L$set$30 # FDE Length
|
||||
LASFDE21:
|
||||
.long LASFDE21-EH_frame1 # FDE CIE offset
|
||||
.quad LFB4-. # FDE initial location
|
||||
.set L$set$31,LFE4-LFB4
|
||||
.quad L$set$31 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32,LCFI23-LFB4
|
||||
.long L$set$32
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x30 # uleb128 0x30
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 3
|
||||
LEFDE21:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15.eh
|
||||
_test_rbx_r12_r13_r14_r15.eh:
|
||||
LSFDE23:
|
||||
.set L$set$33,LEFDE23-LASFDE23
|
||||
.long L$set$33 # FDE Length
|
||||
LASFDE23:
|
||||
.long LASFDE23-EH_frame1 # FDE CIE offset
|
||||
.quad LFB3-. # FDE initial location
|
||||
.set L$set$34,LFE3-LFB3
|
||||
.quad L$set$34 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$35,LCFI29-LFB3
|
||||
.long L$set$35
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x30 # uleb128 0x30
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.align 3
|
||||
LEFDE23:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14_r15.eh
|
||||
_test_rbx_rbp_r12_r13_r14_r15.eh:
|
||||
LSFDE25:
|
||||
.set L$set$36,LEFDE25-LASFDE25
|
||||
.long L$set$36 # FDE Length
|
||||
LASFDE25:
|
||||
.long LASFDE25-EH_frame1 # FDE CIE offset
|
||||
.quad LFB2-. # FDE initial location
|
||||
.set L$set$37,LFE2-LFB2
|
||||
.quad L$set$37 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$38,LCFI36-LFB2
|
||||
.long L$set$38
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x50 # uleb128 0x50
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.align 3
|
||||
LEFDE25:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12.eh
|
||||
_test_rbx_rbp_r12.eh:
|
||||
LSFDE11:
|
||||
.set L$set$24a,LEFDE11-LASFDE11
|
||||
.long L$set$24a # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.quad LFB11-. # FDE initial location
|
||||
.set L$set$25a,LFE11-LFB11
|
||||
.quad L$set$25a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$26a,LCFI11a-LFB11
|
||||
.long L$set$26a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 3
|
||||
LEFDE11:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13.eh
|
||||
_test_rbx_rbp_r12_r13.eh:
|
||||
.set L$set$30a,LEFDE457-LASFDE457
|
||||
.long L$set$30a # FDE Length
|
||||
LASFDE457:
|
||||
.long LASFDE457-EH_frame1 # FDE CIE offset
|
||||
.quad LFB457-. # FDE initial location
|
||||
.set L$set$31a,LFE457-LFB457
|
||||
.quad L$set$31a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32a,LCFI23-LFB4
|
||||
.long L$set$32a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x30 # uleb128 0x30
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 3
|
||||
LEFDE457:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14.eh
|
||||
_test_rbx_rbp_r12_r13_r14.eh:
|
||||
.set L$set$33a,LEFDE117-LASFDE117
|
||||
.long L$set$33a # FDE Length
|
||||
LASFDE117:
|
||||
.long LASFDE117-EH_frame1 # FDE CIE offset
|
||||
.quad LFB17-. # FDE initial location
|
||||
.set L$set$34a,LFE17-LFB17
|
||||
.quad L$set$34a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$35a,LCFI29-LFB3
|
||||
.long L$set$35a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x30 # uleb128 0x30
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.align 3
|
||||
LEFDE117:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
598
testsuite/unwind_test_x86_64_frameless_big.s
Normal file
598
testsuite/unwind_test_x86_64_frameless_big.s
Normal file
@ -0,0 +1,598 @@
|
||||
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -Wl,-no_compact_unwind
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.quad _test_no_reg
|
||||
.quad _test_rbx
|
||||
.quad _test_rbx_r12
|
||||
.quad _test_rbx_r12_r13
|
||||
.quad _test_rbx_r12_r13_r14
|
||||
.quad _test_rbx_r12_r13_r14_r15
|
||||
.quad _test_rbx_rbp
|
||||
.quad _test_rbx_rbp_r12
|
||||
.quad _test_rbx_rbp_r12_r13
|
||||
.quad _test_rbx_rbp_r12_r13_r14
|
||||
.quad _test_rbx_rbp_r12_r13_r14_r15
|
||||
.quad 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB13:
|
||||
subq $160008, %rsp
|
||||
LCFI0:
|
||||
call _uwind_to_main
|
||||
addq $160008, %rsp
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx
|
||||
_test_rbx:
|
||||
LFB10:
|
||||
pushq %rbx
|
||||
LCFI3:
|
||||
subq $160000, %rsp
|
||||
LCFI4:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
addq $160000, %rsp
|
||||
popq %rbx
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_rbx_r12
|
||||
_test_rbx_r12:
|
||||
LFB8:
|
||||
movq %rbx, -16(%rsp)
|
||||
LCFI7:
|
||||
movq %r12, -8(%rsp)
|
||||
LCFI8:
|
||||
subq $160024, %rsp
|
||||
LCFI9:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq 160008(%rsp), %rbx
|
||||
movq 160016(%rsp), %r12
|
||||
addq $160024, %rsp
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp
|
||||
_test_rbx_rbp:
|
||||
LFB7:
|
||||
movq %rbx, -16(%rsp)
|
||||
LCFI10:
|
||||
movq %rbp, -8(%rsp)
|
||||
LCFI11:
|
||||
subq $160024, %rsp
|
||||
LCFI12:
|
||||
movq $0, %rbp
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
movq 160008(%rsp), %rbx
|
||||
movq 160016(%rsp), %rbp
|
||||
addq $160024, %rsp
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13
|
||||
_test_rbx_r12_r13:
|
||||
LFB6:
|
||||
movq %rbx, -24(%rsp)
|
||||
LCFI13:
|
||||
movq %r12, -16(%rsp)
|
||||
LCFI14:
|
||||
movq %r13, -8(%rsp)
|
||||
LCFI15:
|
||||
subq $160024, %rsp
|
||||
LCFI16:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq 160000(%rsp), %rbx
|
||||
movq 160008(%rsp), %r12
|
||||
movq 160016(%rsp), %r13
|
||||
addq $160024, %rsp
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12
|
||||
_test_rbx_rbp_r12:
|
||||
LFB9:
|
||||
movq %rbx, -24(%rsp)
|
||||
movq %rbp, -16(%rsp)
|
||||
movq %r12, -8(%rsp)
|
||||
subq $160024, %rsp
|
||||
LCFI9a:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq 160000(%rsp), %rbx
|
||||
movq 160008(%rsp), %rbp
|
||||
movq 160016(%rsp), %r12
|
||||
addq $160024, %rsp
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14
|
||||
_test_rbx_r12_r13_r14:
|
||||
LFB4:
|
||||
movq %rbx, -32(%rsp)
|
||||
LCFI21:
|
||||
movq %r12, -24(%rsp)
|
||||
LCFI22:
|
||||
movq %r13, -16(%rsp)
|
||||
LCFI23:
|
||||
movq %r14, -8(%rsp)
|
||||
LCFI24:
|
||||
subq $160040, %rsp
|
||||
LCFI25:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq 160008(%rsp), %rbx
|
||||
movq 160016(%rsp), %r12
|
||||
movq 160024(%rsp), %r13
|
||||
movq 160032(%rsp), %r14
|
||||
addq $160040, %rsp
|
||||
ret
|
||||
LFE4:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15
|
||||
_test_rbx_r12_r13_r14_r15:
|
||||
LFB3:
|
||||
movq %rbx, -40(%rsp)
|
||||
LCFI26:
|
||||
movq %r12, -32(%rsp)
|
||||
LCFI27:
|
||||
movq %r13, -24(%rsp)
|
||||
LCFI28:
|
||||
movq %r14, -16(%rsp)
|
||||
LCFI29:
|
||||
movq %r15, -8(%rsp)
|
||||
LCFI30:
|
||||
subq $160040, %rsp
|
||||
LCFI31:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq 160000(%rsp), %rbx
|
||||
movq 160008(%rsp), %r12
|
||||
movq 160016(%rsp), %r13
|
||||
movq 160024(%rsp), %r14
|
||||
movq 160032(%rsp), %r15
|
||||
addq $160040, %rsp
|
||||
ret
|
||||
LFE3:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14_r15
|
||||
_test_rbx_rbp_r12_r13_r14_r15:
|
||||
LFB2:
|
||||
movq %rbx, -48(%rsp)
|
||||
LCFI32:
|
||||
movq %rbp, -40(%rsp)
|
||||
LCFI33:
|
||||
movq %r12, -32(%rsp)
|
||||
LCFI34:
|
||||
movq %r13, -24(%rsp)
|
||||
LCFI35:
|
||||
movq %r14, -16(%rsp)
|
||||
LCFI36:
|
||||
movq %r15, -8(%rsp)
|
||||
LCFI37:
|
||||
subq $160072, %rsp
|
||||
LCFI38:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
movq $0, %r15
|
||||
call _uwind_to_main
|
||||
movq 160024(%rsp), %rbx
|
||||
movq 160032(%rsp), %rbp
|
||||
movq 160040(%rsp), %r12
|
||||
movq 160048(%rsp), %r13
|
||||
movq 160056(%rsp), %r14
|
||||
movq 160064(%rsp), %r15
|
||||
addq $160072, %rsp
|
||||
ret
|
||||
LFE2:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13
|
||||
_test_rbx_rbp_r12_r13:
|
||||
LFB457:
|
||||
movq %rbx, -32(%rsp)
|
||||
LCFI18:
|
||||
movq %rbp, -24(%rsp)
|
||||
LCFI19:
|
||||
movq %r12, -16(%rsp)
|
||||
movq %r13, -8(%rsp)
|
||||
subq $160040, %rsp
|
||||
LCFI20:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
call _uwind_to_main
|
||||
movq 160008(%rsp), %rbx
|
||||
movq 160016(%rsp), %rbp
|
||||
movq 160024(%rsp), %r12
|
||||
movq 160032(%rsp), %r13
|
||||
addq $160040, %rsp
|
||||
ret
|
||||
LFE457:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14
|
||||
_test_rbx_rbp_r12_r13_r14:
|
||||
LFB17:
|
||||
movq %rbx, -40(%rsp)
|
||||
movq %rbp, -32(%rsp)
|
||||
movq %r12, -24(%rsp)
|
||||
movq %r13, -16(%rsp)
|
||||
movq %r14, -8(%rsp)
|
||||
subq $160040, %rsp
|
||||
LFB17a:
|
||||
movq $0, %rbx
|
||||
movq $0, %rbp
|
||||
movq $0, %r12
|
||||
movq $0, %r13
|
||||
movq $0, %r14
|
||||
call _uwind_to_main
|
||||
movq 160000(%rsp), %rbx
|
||||
movq 160008(%rsp), %rbp
|
||||
movq 160016(%rsp), %r12
|
||||
movq 160024(%rsp), %r13
|
||||
movq 160032(%rsp), %r14
|
||||
addq $160040, %rsp
|
||||
ret
|
||||
LFE17:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x78 # sleb128 -8; CIE Data Alignment Factor
|
||||
.byte 0x10 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x90 # DW_CFA_offset, column 0x10
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE3:
|
||||
.set L$set$3,LEFDE3-LASFDE3
|
||||
.long L$set$3 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.quad LFB13-. # FDE initial location
|
||||
.set L$set$4,LFE13-LFB13
|
||||
.quad L$set$4 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI0-LFB13
|
||||
.long L$set$5
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x90,0xe2,0x9 # uleb128 0x27110
|
||||
.align 3
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_rbx.eh
|
||||
_test_rbx.eh:
|
||||
LSFDE9:
|
||||
.set L$set$12,LEFDE9-LASFDE9
|
||||
.long L$set$12 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.quad LFB10-. # FDE initial location
|
||||
.set L$set$13,LFE10-LFB10
|
||||
.quad L$set$13 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14,LCFI3-LFB10
|
||||
.long L$set$14
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15,LCFI4-LCFI3
|
||||
.long L$set$15
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x90,0xe2,0x9 # uleb128 0x27110
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 3
|
||||
LEFDE9:
|
||||
|
||||
|
||||
.globl _test_rbx_r12.eh
|
||||
_test_rbx_r12.eh:
|
||||
LSFDE13:
|
||||
.set L$set$20,LEFDE13-LASFDE13
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.quad LFB8-. # FDE initial location
|
||||
.set L$set$21,LFE8-LFB8
|
||||
.quad L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI9-LFB8
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xe2,0x9 # uleb128 0x27120
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE13:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp.eh
|
||||
_test_rbx_rbp.eh:
|
||||
LSFDE14:
|
||||
.set L$set$23,LEFDE14-LASFDE14
|
||||
.long L$set$23 # FDE Length
|
||||
LASFDE14:
|
||||
.long LASFDE14-EH_frame1 # FDE CIE offset
|
||||
.quad LFB7-. # FDE initial location
|
||||
.set L$set$24,LFE7-LFB7
|
||||
.quad L$set$24 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$25,LCFI12-LFB7
|
||||
.long L$set$25
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xe2,0x9 # uleb128 0x27120
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE14:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13.eh
|
||||
_test_rbx_r12_r13.eh:
|
||||
LSFDE17:
|
||||
.set L$set$26,LEFDE17-LASFDE17
|
||||
.long L$set$26 # FDE Length
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1 # FDE CIE offset
|
||||
.quad LFB6-. # FDE initial location
|
||||
.set L$set$27,LFE6-LFB6
|
||||
.quad L$set$27 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$28,LCFI16-LFB6
|
||||
.long L$set$28
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xe2,0x9 # uleb128 0x27120
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 3
|
||||
LEFDE17:
|
||||
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14.eh
|
||||
_test_rbx_r12_r13_r14.eh:
|
||||
LSFDE21:
|
||||
.set L$set$32,LEFDE21-LASFDE21
|
||||
.long L$set$32 # FDE Length
|
||||
LASFDE21:
|
||||
.long LASFDE21-EH_frame1 # FDE CIE offset
|
||||
.quad LFB4-. # FDE initial location
|
||||
.set L$set$33,LFE4-LFB4
|
||||
.quad L$set$33 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI25-LFB4
|
||||
.long L$set$34
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xb0,0xe2,0x9 # uleb128 0x27130
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 3
|
||||
LEFDE21:
|
||||
|
||||
|
||||
.globl _test_rbx_r12_r13_r14_r15.eh
|
||||
_test_rbx_r12_r13_r14_r15.eh:
|
||||
LSFDE23:
|
||||
.set L$set$35,LEFDE23-LASFDE23
|
||||
.long L$set$35 # FDE Length
|
||||
LASFDE23:
|
||||
.long LASFDE23-EH_frame1 # FDE CIE offset
|
||||
.quad LFB3-. # FDE initial location
|
||||
.set L$set$36,LFE3-LFB3
|
||||
.quad L$set$36 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$37,LCFI31-LFB3
|
||||
.long L$set$37
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xb0,0xe2,0x9 # uleb128 0x27130
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.align 3
|
||||
LEFDE23:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14_r15.eh
|
||||
_test_rbx_rbp_r12_r13_r14_r15.eh:
|
||||
LSFDE25:
|
||||
.set L$set$38,LEFDE25-LASFDE25
|
||||
.long L$set$38 # FDE Length
|
||||
LASFDE25:
|
||||
.long LASFDE25-EH_frame1 # FDE CIE offset
|
||||
.quad LFB2-. # FDE initial location
|
||||
.set L$set$39,LFE2-LFB2
|
||||
.quad L$set$39 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$40,LCFI38-LFB2
|
||||
.long L$set$40
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xd0,0xe2,0x9 # uleb128 0x27150
|
||||
.byte 0x8f # DW_CFA_offset, column 0xf
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x7 # uleb128 0x7
|
||||
.align 3
|
||||
LEFDE25:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13.eh
|
||||
_test_rbx_rbp_r12_r13.eh:
|
||||
LSFDE11:
|
||||
.set L$set$17a,LEFDE11-LASFDE11
|
||||
.long L$set$17a # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.quad LFB457-. # FDE initial location
|
||||
.set L$set$18a,LFE457-LFB457
|
||||
.quad L$set$18a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19a,LCFI20-LFB457
|
||||
.long L$set$19a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xb0,0xe2,0x9 # uleb128 0x27130
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 3
|
||||
LEFDE11:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12_r13_r14.eh
|
||||
_test_rbx_rbp_r12_r13_r14.eh:
|
||||
LSFDE7:
|
||||
.set L$set$35a,LEFDE7-LASFDE7
|
||||
.long L$set$35a # FDE Length
|
||||
LASFDE7:
|
||||
.long LASFDE7-EH_frame1 # FDE CIE offset
|
||||
.quad LFB17-. # FDE initial location
|
||||
.set L$set$36a,LFE17-LFB17
|
||||
.quad L$set$36a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$37a,LFB17a-LFB17
|
||||
.long L$set$37a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xb0,0xe2,0x9 # uleb128 0x27130
|
||||
.byte 0x8e # DW_CFA_offset, column 0xe
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x8d # DW_CFA_offset, column 0xd
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x6 # uleb128 0x6
|
||||
.align 3
|
||||
LEFDE7:
|
||||
|
||||
|
||||
.globl _test_rbx_rbp_r12.eh
|
||||
_test_rbx_rbp_r12.eh:
|
||||
LSFDE19:
|
||||
.set L$set$26a,LEFDE19-LASFDE19
|
||||
.long L$set$26a # FDE Length
|
||||
LASFDE19:
|
||||
.long LASFDE19-EH_frame1 # FDE CIE offset
|
||||
.quad LFB9-. # FDE initial location
|
||||
.set L$set$27a,LFE9-LFB9
|
||||
.quad L$set$27a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$28a,LCFI9a-LFB9
|
||||
.long L$set$28a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xe2,0x9 # uleb128 0x27120
|
||||
.byte 0x8c # DW_CFA_offset, column 0xc
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 3
|
||||
LEFDE19:
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
311
testsuite/unwind_test_x86_64_unusual.s
Normal file
311
testsuite/unwind_test_x86_64_unusual.s
Normal file
@ -0,0 +1,311 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86_64.s -arch x86_64 -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.quad _test_no_reg
|
||||
.quad Ltest_rbx
|
||||
.quad _test_rbx_pad_r12
|
||||
.quad _test_rbx_same_value
|
||||
.quad _test_rbx_same_register
|
||||
.quad 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
|
||||
.globl _test_big_frameless_stack_odd_dwarf
|
||||
_test_big_frameless_stack_odd_dwarf:
|
||||
L100:
|
||||
subq $160016, %rsp
|
||||
L102:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
addq $160016, %rsp
|
||||
ret
|
||||
L103:
|
||||
|
||||
|
||||
LFE14:
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB13:
|
||||
pushq %rbp
|
||||
LCFI2:
|
||||
movq %rsp, %rbp
|
||||
LCFI3:
|
||||
call _uwind_to_main
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
Ltest_rbx:
|
||||
LFB10:
|
||||
pushq %rbp
|
||||
LCFI8:
|
||||
movq %rsp, %rbp
|
||||
LCFI9:
|
||||
pushq %rbx
|
||||
LCFI10:
|
||||
subq $8, %rsp
|
||||
LCFI11:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
addq $8, %rsp
|
||||
popq %rbx
|
||||
leave
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_rbx_pad_r12
|
||||
_test_rbx_pad_r12:
|
||||
LFB8:
|
||||
pushq %rbp
|
||||
LCFI16:
|
||||
movq %rsp, %rbp
|
||||
LCFI17:
|
||||
movq %rbx, -56(%rbp)
|
||||
LCFI18:
|
||||
movq %r12, -8(%rbp)
|
||||
LCFI19:
|
||||
subq $64, %rsp
|
||||
LCFI20:
|
||||
movq $0, %rbx
|
||||
movq $0, %r12
|
||||
call _uwind_to_main
|
||||
movq (%rsp), %rbx
|
||||
movq 8(%rsp), %r12
|
||||
leave
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
.globl _test_rbx_same_value
|
||||
_test_rbx_same_value:
|
||||
LFB10b:
|
||||
jmp L33
|
||||
pushq %rbx
|
||||
LCFI3b:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
popq %rbx
|
||||
ret
|
||||
L33:
|
||||
pushq $0
|
||||
call _uwind_to_main
|
||||
popq %rax
|
||||
ret
|
||||
LFE10b:
|
||||
|
||||
|
||||
.globl _test_rbx_same_register
|
||||
_test_rbx_same_register:
|
||||
LFB10c:
|
||||
jmp L34
|
||||
pushq %rbx
|
||||
LCFI3c:
|
||||
movq $0, %rbx
|
||||
call _uwind_to_main
|
||||
popq %rbx
|
||||
ret
|
||||
L34:
|
||||
pushq $0
|
||||
call _uwind_to_main
|
||||
popq %rax
|
||||
ret
|
||||
LFE10c:
|
||||
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
.ascii "zR\0"
|
||||
.byte 0x1
|
||||
.byte 0x78
|
||||
.byte 0x10
|
||||
.byte 0x1
|
||||
.byte 0x10
|
||||
.byte 0xc
|
||||
.byte 0x7
|
||||
.byte 0x8
|
||||
.byte 0x90
|
||||
.byte 0x1
|
||||
.align 3
|
||||
LECIE1:
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE3:
|
||||
.set L$set$5,LEFDE3-LASFDE3
|
||||
.long L$set$5
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1
|
||||
.quad LFB13-.
|
||||
.set L$set$6,LFE13-LFB13
|
||||
.quad L$set$6
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$7,LCFI2-LFB13
|
||||
.long L$set$7
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$8,LCFI3-LCFI2
|
||||
.long L$set$8
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.align 3
|
||||
LEFDE3:
|
||||
|
||||
Ltest_rbx.eh:
|
||||
LSFDE9:
|
||||
.set L$set$17,LEFDE9-LASFDE9
|
||||
.long L$set$17
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1
|
||||
.quad LFB10-.
|
||||
.set L$set$18,LFE10-LFB10
|
||||
.quad L$set$18
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$19,LCFI8-LFB10
|
||||
.long L$set$19
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$20,LCFI9-LCFI8
|
||||
.long L$set$20
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$21,LCFI11-LCFI9
|
||||
.long L$set$21
|
||||
.byte 0x83
|
||||
.byte 0x3
|
||||
.align 3
|
||||
LEFDE9:
|
||||
|
||||
.globl _test_rbx_pad_r12.eh
|
||||
_test_rbx_pad_r12.eh:
|
||||
LSFDE13:
|
||||
.set L$set$27,LEFDE13-LASFDE13
|
||||
.long L$set$27
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1
|
||||
.quad LFB8-.
|
||||
.set L$set$28,LFE8-LFB8
|
||||
.quad L$set$28
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$29,LCFI16-LFB8
|
||||
.long L$set$29
|
||||
.byte 0xe
|
||||
.byte 0x10
|
||||
.byte 0x86
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$30,LCFI17-LCFI16
|
||||
.long L$set$30
|
||||
.byte 0xd
|
||||
.byte 0x6
|
||||
.byte 0x4
|
||||
.set L$set$31,LCFI20-LCFI17
|
||||
.long L$set$31
|
||||
.byte 0x8c
|
||||
.byte 0x3
|
||||
.byte 0x83
|
||||
.byte 0x9
|
||||
.align 3
|
||||
LEFDE13:
|
||||
|
||||
|
||||
|
||||
.globl _test_big_frameless_stack_odd_dwarf.eh
|
||||
_test_big_frameless_stack_odd_dwarf.eh:
|
||||
.set L$set$12a,LEFDE9a-LASFDE9a
|
||||
.long L$set$12a # FDE Length
|
||||
LASFDE9a:
|
||||
.long LASFDE9a-EH_frame1 # FDE CIE offset
|
||||
.quad L100-. # FDE initial location
|
||||
.set L$set$13a,L103-L100
|
||||
.quad L$set$13a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.long 7
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x07 # uleb128 7
|
||||
.byte 0x90,0xe2,0x9 # uleb128 0x27110
|
||||
.align 3
|
||||
LEFDE9a:
|
||||
|
||||
|
||||
.globl _test_rbx_same_value.eh
|
||||
_test_rbx_same_value.eh:
|
||||
LSFDE9b:
|
||||
.set L$set$12,LEFDE9b-LASFDE9b
|
||||
.long L$set$12 # FDE Length
|
||||
LASFDE9b:
|
||||
.long LASFDE9b-EH_frame1 # FDE CIE offset
|
||||
.quad LFB10b-. # FDE initial location
|
||||
.set L$set$13,LFE10b-LFB10b
|
||||
.quad L$set$13 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14,LCFI3b-LFB10b
|
||||
.long L$set$14
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15,L33-LCFI3b
|
||||
.long L$set$15
|
||||
.byte 0x08 # DW_CFA_same_value
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE9b:
|
||||
|
||||
|
||||
.globl _test_rbx_same_register.eh
|
||||
_test_rbx_same_register.eh:
|
||||
LSFDE9c:
|
||||
.set L$set$12c,LEFDE9c-LASFDE9c
|
||||
.long L$set$12c # FDE Length
|
||||
LASFDE9c:
|
||||
.long LASFDE9c-EH_frame1 # FDE CIE offset
|
||||
.quad LFB10c-. # FDE initial location
|
||||
.set L$set$16c,LFE10c-LFB10c
|
||||
.quad L$set$16c # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$17c,LCFI3c-LFB10c
|
||||
.long L$set$17c
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x10 # uleb128 0x10
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18c,L34-LCFI3c
|
||||
.long L$set$18c
|
||||
.byte 0x09 # DW_CFA_register
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 3
|
||||
LEFDE9c:
|
||||
|
||||
|
589
testsuite/unwind_test_x86_disable_compact_frame.s
Normal file
589
testsuite/unwind_test_x86_disable_compact_frame.s
Normal file
@ -0,0 +1,589 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_no_reg
|
||||
.long _test_ebx
|
||||
.long _test_esi
|
||||
.long _test_edi
|
||||
.long _test_ebx_esi
|
||||
.long _test_esi_edi
|
||||
.long _test_ebx_edi
|
||||
.long _test_ebx_esi_edi
|
||||
.long _test_edi_esi_ebx
|
||||
.long _test_pad_ebx_edi
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_ebx
|
||||
_test_ebx:
|
||||
LFB13:
|
||||
pushl %ebp
|
||||
LCFI2:
|
||||
movl %esp, %ebp
|
||||
LCFI3:
|
||||
pushl %ebx
|
||||
LCFI4:
|
||||
subl $20, %esp
|
||||
LCFI5:
|
||||
movl $0, %ebx
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %ebx
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB12:
|
||||
pushl %ebp
|
||||
LCFI6:
|
||||
movl %esp, %ebp
|
||||
LCFI7:
|
||||
subl $24, %esp
|
||||
LCFI8:
|
||||
call _uwind_to_main
|
||||
leave
|
||||
ret
|
||||
LFE12:
|
||||
|
||||
.globl _test_esi
|
||||
_test_esi:
|
||||
LFB10:
|
||||
pushl %ebp
|
||||
LCFI13:
|
||||
movl %esp, %ebp
|
||||
LCFI14:
|
||||
pushl %esi
|
||||
LCFI15:
|
||||
subl $20, %esp
|
||||
LCFI16:
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
.globl _test_edi
|
||||
_test_edi:
|
||||
LFB11:
|
||||
pushl %ebp
|
||||
LCFI9:
|
||||
movl %esp, %ebp
|
||||
LCFI10:
|
||||
pushl %edi
|
||||
LCFI11:
|
||||
subl $20, %esp
|
||||
LCFI12:
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
LFE11:
|
||||
|
||||
.globl _test_ebx_esi
|
||||
_test_ebx_esi:
|
||||
LFB9:
|
||||
pushl %ebp
|
||||
LCFI17:
|
||||
movl %esp, %ebp
|
||||
LCFI18:
|
||||
subl $24, %esp
|
||||
LCFI19:
|
||||
movl %ebx, -8(%ebp)
|
||||
LCFI20:
|
||||
movl %esi, -4(%ebp)
|
||||
LCFI21:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %ebx
|
||||
movl -4(%ebp), %esi
|
||||
leave
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
.globl _test_esi_edi
|
||||
_test_esi_edi:
|
||||
LFB8:
|
||||
pushl %ebp
|
||||
LCFI22:
|
||||
movl %esp, %ebp
|
||||
LCFI23:
|
||||
subl $24, %esp
|
||||
LCFI24:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI25:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI26:
|
||||
movl $0, %edi
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
.globl _test_ebx_edi
|
||||
_test_ebx_edi:
|
||||
LFB91:
|
||||
pushl %ebp
|
||||
LCFI171:
|
||||
movl %esp, %ebp
|
||||
LCFI181:
|
||||
subl $24, %esp
|
||||
LCFI191:
|
||||
movl %ebx, -8(%ebp)
|
||||
LCFI201:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI211:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %ebx
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE91:
|
||||
|
||||
.globl _test_ebx_esi_edi
|
||||
_test_ebx_esi_edi:
|
||||
LFB7:
|
||||
pushl %ebp
|
||||
LCFI27:
|
||||
movl %esp, %ebp
|
||||
LCFI28:
|
||||
subl $40, %esp
|
||||
LCFI29:
|
||||
movl %ebx, -12(%ebp)
|
||||
LCFI30:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI31:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI32:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -12(%ebp), %ebx
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_edi_esi_ebx
|
||||
_test_edi_esi_ebx:
|
||||
LFB7a:
|
||||
pushl %ebp
|
||||
LCFI27a:
|
||||
movl %esp, %ebp
|
||||
LCFI28a:
|
||||
subl $40, %esp
|
||||
LCFI29a:
|
||||
movl %edi, -12(%ebp)
|
||||
LCFI30a:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI31a:
|
||||
movl %ebx, -4(%ebp)
|
||||
LCFI32a:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -12(%ebp), %edi
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
||||
LFE7a:
|
||||
|
||||
|
||||
|
||||
.globl _test_pad_ebx_edi
|
||||
_test_pad_ebx_edi:
|
||||
LFB91a:
|
||||
pushl %ebp
|
||||
LCFI171a:
|
||||
movl %esp, %ebp
|
||||
LCFI181a:
|
||||
subl $88, %esp
|
||||
LCFI191a:
|
||||
movl %ebx, -72(%ebp)
|
||||
LCFI201a:
|
||||
movl %edi, -68(%ebp)
|
||||
LCFI211a:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -72(%ebp), %ebx
|
||||
movl -68(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE91a:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8 // duplicate save in CIE means disable compact unwind encoding
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE5:
|
||||
.set L$set$6,LEFDE5-LASFDE5
|
||||
.long L$set$6 # FDE Length
|
||||
LASFDE5:
|
||||
.long LASFDE5-EH_frame1 # FDE CIE offset
|
||||
.long LFB12-. # FDE initial location
|
||||
.set L$set$7,LFE12-LFB12
|
||||
.long L$set$7 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$8,LCFI6-LFB12
|
||||
.long L$set$8
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$9,LCFI7-LCFI6
|
||||
.long L$set$9
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE5:
|
||||
|
||||
|
||||
.globl _test_ebx.eh
|
||||
_test_ebx.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.long LFB13-. # FDE initial location
|
||||
.set L$set$2,LFE13-LFB13
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI2-LFB13
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI3-LCFI2
|
||||
.long L$set$4
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI5-LCFI3
|
||||
.long L$set$5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_esi.eh
|
||||
_test_esi.eh:
|
||||
LSFDE9:
|
||||
.set L$set$15,LEFDE9-LASFDE9
|
||||
.long L$set$15 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.long LFB10-. # FDE initial location
|
||||
.set L$set$16,LFE10-LFB10
|
||||
.long L$set$16 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$17,LCFI13-LFB10
|
||||
.long L$set$17
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18,LCFI14-LCFI13
|
||||
.long L$set$18
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19,LCFI16-LCFI14
|
||||
.long L$set$19
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE9:
|
||||
|
||||
|
||||
.globl _test_edi.eh
|
||||
_test_edi.eh:
|
||||
LSFDE10:
|
||||
.set L$set$15a,LEFDE10-LASFDE10
|
||||
.long L$set$15a # FDE Length
|
||||
LASFDE10:
|
||||
.long LASFDE10-EH_frame1 # FDE CIE offset
|
||||
.long LFB11-. # FDE initial location
|
||||
.set L$set$16a,LFE11-LFB11
|
||||
.long L$set$16a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$17a,LCFI9-LFB11
|
||||
.long L$set$17a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18a,LCFI10-LCFI9
|
||||
.long L$set$18a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19a,LCFI12-LCFI10
|
||||
.long L$set$19a
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE10:
|
||||
|
||||
.globl _test_ebx_esi.eh
|
||||
_test_ebx_esi.eh:
|
||||
LSFDE11:
|
||||
.set L$set$20,LEFDE11-LASFDE11
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.long LFB9-. # FDE initial location
|
||||
.set L$set$21,LFE9-LFB9
|
||||
.long L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI17-LFB9
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI18-LCFI17
|
||||
.long L$set$23
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24,LCFI21-LCFI18
|
||||
.long L$set$24
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE11:
|
||||
|
||||
.globl _test_esi_edi.eh
|
||||
_test_esi_edi.eh:
|
||||
LSFDE13:
|
||||
.set L$set$25,LEFDE13-LASFDE13
|
||||
.long L$set$25 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.long LFB8-. # FDE initial location
|
||||
.set L$set$26,LFE8-LFB8
|
||||
.long L$set$26 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$27,LCFI22-LFB8
|
||||
.long L$set$27
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$28,LCFI23-LCFI22
|
||||
.long L$set$28
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$29,LCFI26-LCFI23
|
||||
.long L$set$29
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE13:
|
||||
|
||||
.globl _test_ebx_edi.eh
|
||||
_test_ebx_edi.eh:
|
||||
LSFDE111:
|
||||
.set L$set$20a,LEFDE11-LASFDE11
|
||||
.long L$set$20a # FDE Length
|
||||
LASFDE111:
|
||||
.long LASFDE111-EH_frame1 # FDE CIE offset
|
||||
.long LFB91-. # FDE initial location
|
||||
.set L$set$21a,LFE91-LFB91
|
||||
.long L$set$21a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22a,LCFI171-LFB91
|
||||
.long L$set$22a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23a,LCFI181-LCFI171
|
||||
.long L$set$23a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24a,LCFI211-LCFI181
|
||||
.long L$set$24a
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE111:
|
||||
|
||||
.globl _test_ebx_esi_edi.eh
|
||||
_test_ebx_esi_edi.eh:
|
||||
LSFDE15:
|
||||
.set L$set$30,LEFDE15-LASFDE15
|
||||
.long L$set$30 # FDE Length
|
||||
LASFDE15:
|
||||
.long LASFDE15-EH_frame1 # FDE CIE offset
|
||||
.long LFB7-. # FDE initial location
|
||||
.set L$set$31,LFE7-LFB7
|
||||
.long L$set$31 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32,LCFI27-LFB7
|
||||
.long L$set$32
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33,LCFI28-LCFI27
|
||||
.long L$set$33
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI32-LCFI28
|
||||
.long L$set$34
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE15:
|
||||
|
||||
|
||||
.globl _test_edi_esi_ebx.eh
|
||||
_test_edi_esi_ebx.eh:
|
||||
LSFDE15a:
|
||||
.set L$set$30a,LEFDE15a-LASFDE15a
|
||||
.long L$set$30a # FDE Length
|
||||
LASFDE15a:
|
||||
.long LASFDE15a-EH_frame1 # FDE CIE offset
|
||||
.long LFB7a-. # FDE initial location
|
||||
.set L$set$31a,LFE7a-LFB7a
|
||||
.long L$set$31a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32a,LCFI27a-LFB7a
|
||||
.long L$set$32a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33a,LCFI28a-LCFI27a
|
||||
.long L$set$33a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34a,LCFI32a-LCFI28a
|
||||
.long L$set$34a
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE15a:
|
||||
|
||||
|
||||
.globl _test_pad_ebx_edi.eh
|
||||
_test_pad_ebx_edi.eh:
|
||||
LSFDE111a:
|
||||
.set L$set$20b,LEFDE111a-LASFDE111a
|
||||
.long L$set$20b # FDE Length
|
||||
LASFDE111a:
|
||||
.long LASFDE111a-EH_frame1 # FDE CIE offset
|
||||
.long LFB91a-. # FDE initial location
|
||||
.set L$set$21b,LFE91a-LFB91a
|
||||
.long L$set$21b # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22b,LCFI171a-LFB91a
|
||||
.long L$set$22b
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23b,LCFI181a-LCFI171a
|
||||
.long L$set$23b
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24b,LCFI211a-LCFI181a
|
||||
.long L$set$24b
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x13 # uleb128 0x13
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x14 # uleb128 0x14
|
||||
.align 2
|
||||
LEFDE111a:
|
||||
|
||||
|
||||
.subsections_via_symbols
|
671
testsuite/unwind_test_x86_frame.s
Normal file
671
testsuite/unwind_test_x86_frame.s
Normal file
@ -0,0 +1,671 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -DUSE_COMPACT_UNWIND=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -DUSE_EH_FRAME=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -DUSE_COMPACT_UNWIND=1 -DUSE_EH_FRAME=1
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -DUSE_EH_FRAME=1 -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_no_reg
|
||||
.long _test_ebx
|
||||
.long _test_esi
|
||||
.long _test_edi
|
||||
.long _test_ebx_esi
|
||||
.long _test_esi_edi
|
||||
.long _test_ebx_edi
|
||||
.long _test_ebx_esi_edi
|
||||
.long _test_edi_esi_ebx
|
||||
.long _test_pad_ebx_edi
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_ebx
|
||||
_test_ebx:
|
||||
LFB13:
|
||||
pushl %ebp
|
||||
LCFI2:
|
||||
movl %esp, %ebp
|
||||
LCFI3:
|
||||
pushl %ebx
|
||||
LCFI4:
|
||||
subl $20, %esp
|
||||
LCFI5:
|
||||
movl $0, %ebx
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %ebx
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB12:
|
||||
pushl %ebp
|
||||
LCFI6:
|
||||
movl %esp, %ebp
|
||||
LCFI7:
|
||||
subl $24, %esp
|
||||
LCFI8:
|
||||
call _uwind_to_main
|
||||
leave
|
||||
ret
|
||||
LFE12:
|
||||
|
||||
.globl _test_esi
|
||||
_test_esi:
|
||||
LFB10:
|
||||
pushl %ebp
|
||||
LCFI13:
|
||||
movl %esp, %ebp
|
||||
LCFI14:
|
||||
pushl %esi
|
||||
LCFI15:
|
||||
subl $20, %esp
|
||||
LCFI16:
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %esi
|
||||
leave
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
.globl _test_edi
|
||||
_test_edi:
|
||||
LFB11:
|
||||
pushl %ebp
|
||||
LCFI9:
|
||||
movl %esp, %ebp
|
||||
LCFI10:
|
||||
pushl %edi
|
||||
LCFI11:
|
||||
subl $20, %esp
|
||||
LCFI12:
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
addl $20, %esp
|
||||
popl %edi
|
||||
leave
|
||||
ret
|
||||
LFE11:
|
||||
|
||||
.globl _test_ebx_esi
|
||||
_test_ebx_esi:
|
||||
LFB9:
|
||||
pushl %ebp
|
||||
LCFI17:
|
||||
movl %esp, %ebp
|
||||
LCFI18:
|
||||
subl $24, %esp
|
||||
LCFI19:
|
||||
movl %ebx, -8(%ebp)
|
||||
LCFI20:
|
||||
movl %esi, -4(%ebp)
|
||||
LCFI21:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %ebx
|
||||
movl -4(%ebp), %esi
|
||||
leave
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
.globl _test_esi_edi
|
||||
_test_esi_edi:
|
||||
LFB8:
|
||||
pushl %ebp
|
||||
LCFI22:
|
||||
movl %esp, %ebp
|
||||
LCFI23:
|
||||
subl $24, %esp
|
||||
LCFI24:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI25:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI26:
|
||||
movl $0, %edi
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
.globl _test_ebx_edi
|
||||
_test_ebx_edi:
|
||||
LFB91:
|
||||
pushl %ebp
|
||||
LCFI171:
|
||||
movl %esp, %ebp
|
||||
LCFI181:
|
||||
subl $24, %esp
|
||||
LCFI191:
|
||||
movl %ebx, -8(%ebp)
|
||||
LCFI201:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI211:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -8(%ebp), %ebx
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE91:
|
||||
|
||||
.globl _test_ebx_esi_edi
|
||||
_test_ebx_esi_edi:
|
||||
LFB7:
|
||||
pushl %ebp
|
||||
LCFI27:
|
||||
movl %esp, %ebp
|
||||
LCFI28:
|
||||
subl $40, %esp
|
||||
LCFI29:
|
||||
movl %ebx, -12(%ebp)
|
||||
LCFI30:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI31:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI32:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -12(%ebp), %ebx
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_edi_esi_ebx
|
||||
_test_edi_esi_ebx:
|
||||
LFB7a:
|
||||
pushl %ebp
|
||||
LCFI27a:
|
||||
movl %esp, %ebp
|
||||
LCFI28a:
|
||||
subl $40, %esp
|
||||
LCFI29a:
|
||||
movl %edi, -12(%ebp)
|
||||
LCFI30a:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI31a:
|
||||
movl %ebx, -4(%ebp)
|
||||
LCFI32a:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -12(%ebp), %edi
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
||||
LFE7a:
|
||||
|
||||
|
||||
|
||||
.globl _test_pad_ebx_edi
|
||||
_test_pad_ebx_edi:
|
||||
LFB91a:
|
||||
pushl %ebp
|
||||
LCFI171a:
|
||||
movl %esp, %ebp
|
||||
LCFI181a:
|
||||
subl $88, %esp
|
||||
LCFI191a:
|
||||
movl %ebx, -72(%ebp)
|
||||
LCFI201a:
|
||||
movl %edi, -68(%ebp)
|
||||
LCFI211a:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -72(%ebp), %ebx
|
||||
movl -68(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE91a:
|
||||
|
||||
|
||||
#if USE_EH_FRAME
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE5:
|
||||
.set L$set$6,LEFDE5-LASFDE5
|
||||
.long L$set$6 # FDE Length
|
||||
LASFDE5:
|
||||
.long LASFDE5-EH_frame1 # FDE CIE offset
|
||||
.long LFB12-. # FDE initial location
|
||||
.set L$set$7,LFE12-LFB12
|
||||
.long L$set$7 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$8,LCFI6-LFB12
|
||||
.long L$set$8
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$9,LCFI7-LCFI6
|
||||
.long L$set$9
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE5:
|
||||
|
||||
|
||||
.globl _test_ebx.eh
|
||||
_test_ebx.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.long LFB13-. # FDE initial location
|
||||
.set L$set$2,LFE13-LFB13
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI2-LFB13
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI3-LCFI2
|
||||
.long L$set$4
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI5-LCFI3
|
||||
.long L$set$5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_esi.eh
|
||||
_test_esi.eh:
|
||||
LSFDE9:
|
||||
.set L$set$15,LEFDE9-LASFDE9
|
||||
.long L$set$15 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.long LFB10-. # FDE initial location
|
||||
.set L$set$16,LFE10-LFB10
|
||||
.long L$set$16 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$17,LCFI13-LFB10
|
||||
.long L$set$17
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18,LCFI14-LCFI13
|
||||
.long L$set$18
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19,LCFI16-LCFI14
|
||||
.long L$set$19
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE9:
|
||||
|
||||
|
||||
.globl _test_edi.eh
|
||||
_test_edi.eh:
|
||||
LSFDE10:
|
||||
.set L$set$15a,LEFDE10-LASFDE10
|
||||
.long L$set$15a # FDE Length
|
||||
LASFDE10:
|
||||
.long LASFDE10-EH_frame1 # FDE CIE offset
|
||||
.long LFB11-. # FDE initial location
|
||||
.set L$set$16a,LFE11-LFB11
|
||||
.long L$set$16a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$17a,LCFI9-LFB11
|
||||
.long L$set$17a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18a,LCFI10-LCFI9
|
||||
.long L$set$18a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19a,LCFI12-LCFI10
|
||||
.long L$set$19a
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE10:
|
||||
|
||||
.globl _test_ebx_esi.eh
|
||||
_test_ebx_esi.eh:
|
||||
LSFDE11:
|
||||
.set L$set$20,LEFDE11-LASFDE11
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.long LFB9-. # FDE initial location
|
||||
.set L$set$21,LFE9-LFB9
|
||||
.long L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI17-LFB9
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI18-LCFI17
|
||||
.long L$set$23
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24,LCFI21-LCFI18
|
||||
.long L$set$24
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE11:
|
||||
|
||||
.globl _test_esi_edi.eh
|
||||
_test_esi_edi.eh:
|
||||
LSFDE13:
|
||||
.set L$set$25,LEFDE13-LASFDE13
|
||||
.long L$set$25 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.long LFB8-. # FDE initial location
|
||||
.set L$set$26,LFE8-LFB8
|
||||
.long L$set$26 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$27,LCFI22-LFB8
|
||||
.long L$set$27
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$28,LCFI23-LCFI22
|
||||
.long L$set$28
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$29,LCFI26-LCFI23
|
||||
.long L$set$29
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE13:
|
||||
|
||||
.globl _test_ebx_edi.eh
|
||||
_test_ebx_edi.eh:
|
||||
LSFDE111:
|
||||
.set L$set$20a,LEFDE11-LASFDE11
|
||||
.long L$set$20a # FDE Length
|
||||
LASFDE111:
|
||||
.long LASFDE111-EH_frame1 # FDE CIE offset
|
||||
.long LFB91-. # FDE initial location
|
||||
.set L$set$21a,LFE91-LFB91
|
||||
.long L$set$21a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22a,LCFI171-LFB91
|
||||
.long L$set$22a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23a,LCFI181-LCFI171
|
||||
.long L$set$23a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24a,LCFI211-LCFI181
|
||||
.long L$set$24a
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE111:
|
||||
|
||||
.globl _test_ebx_esi_edi.eh
|
||||
_test_ebx_esi_edi.eh:
|
||||
LSFDE15:
|
||||
.set L$set$30,LEFDE15-LASFDE15
|
||||
.long L$set$30 # FDE Length
|
||||
LASFDE15:
|
||||
.long LASFDE15-EH_frame1 # FDE CIE offset
|
||||
.long LFB7-. # FDE initial location
|
||||
.set L$set$31,LFE7-LFB7
|
||||
.long L$set$31 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32,LCFI27-LFB7
|
||||
.long L$set$32
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33,LCFI28-LCFI27
|
||||
.long L$set$33
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI32-LCFI28
|
||||
.long L$set$34
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE15:
|
||||
|
||||
|
||||
.globl _test_edi_esi_ebx.eh
|
||||
_test_edi_esi_ebx.eh:
|
||||
LSFDE15a:
|
||||
.set L$set$30a,LEFDE15a-LASFDE15a
|
||||
.long L$set$30a # FDE Length
|
||||
LASFDE15a:
|
||||
.long LASFDE15a-EH_frame1 # FDE CIE offset
|
||||
.long LFB7a-. # FDE initial location
|
||||
.set L$set$31a,LFE7a-LFB7a
|
||||
.long L$set$31a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32a,LCFI27a-LFB7a
|
||||
.long L$set$32a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33a,LCFI28a-LCFI27a
|
||||
.long L$set$33a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34a,LCFI32a-LCFI28a
|
||||
.long L$set$34a
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE15a:
|
||||
|
||||
|
||||
.globl _test_pad_ebx_edi.eh
|
||||
_test_pad_ebx_edi.eh:
|
||||
LSFDE111a:
|
||||
.set L$set$20b,LEFDE111a-LASFDE111a
|
||||
.long L$set$20b # FDE Length
|
||||
LASFDE111a:
|
||||
.long LASFDE111a-EH_frame1 # FDE CIE offset
|
||||
.long LFB91a-. # FDE initial location
|
||||
.set L$set$21b,LFE91a-LFB91a
|
||||
.long L$set$21b # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22b,LCFI171a-LFB91a
|
||||
.long L$set$22b
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23b,LCFI181a-LCFI171a
|
||||
.long L$set$23b
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24b,LCFI211a-LCFI181a
|
||||
.long L$set$24b
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x13 # uleb128 0x13
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x14 # uleb128 0x14
|
||||
.align 2
|
||||
LEFDE111a:
|
||||
#endif // USE_EH_FRAME
|
||||
|
||||
|
||||
|
||||
#if USE_COMPACT_UNWIND
|
||||
|
||||
.section __LD,__compact_unwind,regular,debug
|
||||
|
||||
.long _test_no_reg
|
||||
.set L101,LFE13-_test_no_reg
|
||||
.long L101
|
||||
.long 0x01000000
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_ebx
|
||||
.set L102,LFE13-_test_ebx
|
||||
.long L102
|
||||
.long 0x01010001
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_esi
|
||||
.set L103,LFE10-_test_esi
|
||||
.long L103
|
||||
.long 0x01010005
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_edi
|
||||
.set L104,LFE11-_test_edi
|
||||
.long L104
|
||||
.long 0x01010004
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_ebx_esi
|
||||
.set L105,LFE9-_test_ebx_esi
|
||||
.long L105
|
||||
.long 0x01020029
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_esi_edi
|
||||
.set L106,LFE8-_test_esi_edi
|
||||
.long L106
|
||||
.long 0x01020025
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_ebx_edi
|
||||
.set L107,LFE91-_test_ebx_edi
|
||||
.long L107
|
||||
.long 0x01020021
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_ebx_esi_edi
|
||||
.set L108,LFE7-_test_ebx_esi_edi
|
||||
.long L108
|
||||
.long 0x01030129
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_edi_esi_ebx
|
||||
.set L109,LFE7a-_test_edi_esi_ebx
|
||||
.long L109
|
||||
.long 0x0103006C
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
.long _test_pad_ebx_edi
|
||||
.set L110,LFE91a-_test_pad_ebx_edi
|
||||
.long L110
|
||||
.long 0x01120021
|
||||
.long 0
|
||||
.long 0
|
||||
|
||||
#endif // USE_COMPACT_UNWIND
|
||||
|
||||
|
||||
.subsections_via_symbols
|
516
testsuite/unwind_test_x86_frameless.s
Normal file
516
testsuite/unwind_test_x86_frameless.s
Normal file
@ -0,0 +1,516 @@
|
||||
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_no_reg
|
||||
.long _test_ebx
|
||||
.long _test_esi
|
||||
.long _test_edi
|
||||
.long _test_ebx_esi
|
||||
.long _test_esi_edi
|
||||
.long _test_esi_edi_ebp
|
||||
.long _test_ebx_esi_edi
|
||||
.long _test_ebx_esi_edi_ebp
|
||||
.long _test_esi_ebp_ebx_edi
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_ebx
|
||||
_test_ebx:
|
||||
LFB13:
|
||||
pushl %ebx
|
||||
LCFI0:
|
||||
subl $24, %esp
|
||||
LCFI1:
|
||||
movl $0, %ebx
|
||||
call _uwind_to_main
|
||||
addl $24, %esp
|
||||
popl %ebx
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB12:
|
||||
subl $28, %esp
|
||||
LCFI2:
|
||||
call _uwind_to_main
|
||||
addl $28, %esp
|
||||
ret
|
||||
LFE12:
|
||||
|
||||
|
||||
.globl _test_esi
|
||||
_test_esi:
|
||||
LFB10:
|
||||
pushl %esi
|
||||
LCFI5:
|
||||
subl $24, %esp
|
||||
LCFI6:
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
addl $24, %esp
|
||||
popl %esi
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_edi
|
||||
_test_edi:
|
||||
LFB11:
|
||||
pushl %edi
|
||||
LCFI3:
|
||||
subl $24, %esp
|
||||
LCFI4:
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
addl $24, %esp
|
||||
popl %edi
|
||||
ret
|
||||
LFE11:
|
||||
|
||||
|
||||
.globl _test_ebx_esi
|
||||
_test_ebx_esi:
|
||||
LFB9:
|
||||
subl $28, %esp
|
||||
LCFI7:
|
||||
movl %ebx, 20(%esp)
|
||||
LCFI8:
|
||||
movl %esi, 24(%esp)
|
||||
LCFI9:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl 20(%esp), %ebx
|
||||
movl 24(%esp), %esi
|
||||
addl $28, %esp
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
.globl _test_esi_edi
|
||||
_test_esi_edi:
|
||||
LFB8:
|
||||
subl $28, %esp
|
||||
LCFI10:
|
||||
movl %esi, 20(%esp)
|
||||
LCFI11:
|
||||
movl %edi, 24(%esp)
|
||||
LCFI12:
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl 20(%esp), %esi
|
||||
movl 24(%esp), %edi
|
||||
addl $28, %esp
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi
|
||||
_test_ebx_esi_edi:
|
||||
LFB7:
|
||||
subl $28, %esp
|
||||
LCFI13:
|
||||
movl %ebx, 16(%esp)
|
||||
LCFI14:
|
||||
movl %esi, 20(%esp)
|
||||
LCFI15:
|
||||
movl %edi, 24(%esp)
|
||||
LCFI16:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl 16(%esp), %ebx
|
||||
movl 20(%esp), %esi
|
||||
movl 24(%esp), %edi
|
||||
addl $28, %esp
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_esi_edi_ebp
|
||||
_test_esi_edi_ebp:
|
||||
LFB6:
|
||||
subl $28, %esp
|
||||
LCFI17:
|
||||
movl %esi, 16(%esp)
|
||||
LCFI18:
|
||||
movl %edi, 20(%esp)
|
||||
LCFI19:
|
||||
movl %ebp, 24(%esp)
|
||||
LCFI20:
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
movl $0, %ebp
|
||||
call _uwind_to_main
|
||||
movl 16(%esp), %esi
|
||||
movl 20(%esp), %edi
|
||||
movl 24(%esp), %ebp
|
||||
addl $28, %esp
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi_ebp
|
||||
_test_ebx_esi_edi_ebp:
|
||||
LFB5:
|
||||
subl $60, %esp
|
||||
LCFI21:
|
||||
movl %ebx, 44(%esp)
|
||||
LCFI22:
|
||||
movl %esi, 48(%esp)
|
||||
LCFI23:
|
||||
movl %edi, 52(%esp)
|
||||
LCFI24:
|
||||
movl %ebp, 56(%esp)
|
||||
LCFI25:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
movl $0, %ebp
|
||||
call _uwind_to_main
|
||||
movl 44(%esp), %ebx
|
||||
movl 48(%esp), %esi
|
||||
movl 52(%esp), %edi
|
||||
movl 56(%esp), %ebp
|
||||
addl $60, %esp
|
||||
ret
|
||||
LFE5:
|
||||
|
||||
.globl _test_esi_ebp_ebx_edi
|
||||
_test_esi_ebp_ebx_edi:
|
||||
LFB5a:
|
||||
subl $60, %esp
|
||||
LCFI21a:
|
||||
movl %esi, 44(%esp)
|
||||
LCFI22a:
|
||||
movl %ebp, 48(%esp)
|
||||
LCFI23a:
|
||||
movl %ebx, 52(%esp)
|
||||
LCFI24a:
|
||||
movl %edi, 56(%esp)
|
||||
LCFI25a:
|
||||
movl $0, %esi
|
||||
movl $0, %ebp
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl 44(%esp), %esi
|
||||
movl 48(%esp), %ebp
|
||||
movl 52(%esp), %ebx
|
||||
movl 56(%esp), %edi
|
||||
addl $60, %esp
|
||||
ret
|
||||
LFE5a:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
.globl _test_ebx.eh
|
||||
_test_ebx.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.long LFB13-. # FDE initial location
|
||||
.set L$set$2,LFE13-LFB13
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI0-LFB13
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI1-LCFI0
|
||||
.long L$set$4
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE5:
|
||||
.set L$set$5,LEFDE5-LASFDE5
|
||||
.long L$set$5 # FDE Length
|
||||
LASFDE5:
|
||||
.long LASFDE5-EH_frame1 # FDE CIE offset
|
||||
.long LFB12-. # FDE initial location
|
||||
.set L$set$6,LFE12-LFB12
|
||||
.long L$set$6 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$7,LCFI2-LFB12
|
||||
.long L$set$7
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.align 2
|
||||
LEFDE5:
|
||||
|
||||
|
||||
.globl _test_esi.eh
|
||||
_test_esi.eh:
|
||||
LSFDE9:
|
||||
.set L$set$12,LEFDE9-LASFDE9
|
||||
.long L$set$12 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.long LFB10-. # FDE initial location
|
||||
.set L$set$13,LFE10-LFB10
|
||||
.long L$set$13 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14,LCFI5-LFB10
|
||||
.long L$set$14
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15,LCFI6-LCFI5
|
||||
.long L$set$15
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE9:
|
||||
|
||||
|
||||
.globl _test_edi.eh
|
||||
_test_edi.eh:
|
||||
LSFDE10:
|
||||
.set L$set$12a,LEFDE10-LASFDE10
|
||||
.long L$set$12a # FDE Length
|
||||
LASFDE10:
|
||||
.long LASFDE10-EH_frame1 # FDE CIE offset
|
||||
.long LFB11-. # FDE initial location
|
||||
.set L$set$13a,LFE11-LFB11
|
||||
.long L$set$13a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14a,LCFI3-LFB11
|
||||
.long L$set$14a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15a,LCFI4-LCFI3
|
||||
.long L$set$15a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE10:
|
||||
|
||||
|
||||
|
||||
.globl _test_ebx_esi.eh
|
||||
_test_ebx_esi.eh:
|
||||
LSFDE11:
|
||||
.set L$set$16,LEFDE11-LASFDE11
|
||||
.long L$set$16 # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.long LFB9-. # FDE initial location
|
||||
.set L$set$17,LFE9-LFB9
|
||||
.long L$set$17 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18,LCFI7-LFB9
|
||||
.long L$set$18
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19,LCFI9-LCFI7
|
||||
.long L$set$19
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE11:
|
||||
|
||||
|
||||
.globl _test_esi_edi.eh
|
||||
_test_esi_edi.eh:
|
||||
LSFDE13:
|
||||
.set L$set$20,LEFDE13-LASFDE13
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.long LFB8-. # FDE initial location
|
||||
.set L$set$21,LFE8-LFB8
|
||||
.long L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI10-LFB8
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI12-LCFI10
|
||||
.long L$set$23
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE13:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi.eh
|
||||
_test_ebx_esi_edi.eh:
|
||||
LSFDE15:
|
||||
.set L$set$24,LEFDE15-LASFDE15
|
||||
.long L$set$24 # FDE Length
|
||||
LASFDE15:
|
||||
.long LASFDE15-EH_frame1 # FDE CIE offset
|
||||
.long LFB7-. # FDE initial location
|
||||
.set L$set$25,LFE7-LFB7
|
||||
.long L$set$25 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$26,LCFI13-LFB7
|
||||
.long L$set$26
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$27,LCFI16-LCFI13
|
||||
.long L$set$27
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE15:
|
||||
|
||||
|
||||
.globl _test_esi_edi_ebp.eh
|
||||
_test_esi_edi_ebp.eh:
|
||||
LSFDE17:
|
||||
.set L$set$28,LEFDE17-LASFDE17
|
||||
.long L$set$28 # FDE Length
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1 # FDE CIE offset
|
||||
.long LFB6-. # FDE initial location
|
||||
.set L$set$29,LFE6-LFB6
|
||||
.long L$set$29 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$30,LCFI17-LFB6
|
||||
.long L$set$30
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x20 # uleb128 0x20
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$31,LCFI20-LCFI17
|
||||
.long L$set$31
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE17:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi_ebp.eh
|
||||
_test_ebx_esi_edi_ebp.eh:
|
||||
LSFDE19:
|
||||
.set L$set$32,LEFDE19-LASFDE19
|
||||
.long L$set$32 # FDE Length
|
||||
LASFDE19:
|
||||
.long LASFDE19-EH_frame1 # FDE CIE offset
|
||||
.long LFB5-. # FDE initial location
|
||||
.set L$set$33,LFE5-LFB5
|
||||
.long L$set$33 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI21-LFB5
|
||||
.long L$set$34
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x40 # uleb128 0x40
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$35,LCFI25-LCFI21
|
||||
.long L$set$35
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE19:
|
||||
|
||||
.globl _test_esi_ebp_ebx_edi.eh
|
||||
_test_esi_ebp_ebx_edi.eh:
|
||||
LSFDE19a:
|
||||
.set L$set$32a,LEFDE19a-LASFDE19a
|
||||
.long L$set$32a # FDE Length
|
||||
LASFDE19a:
|
||||
.long LASFDE19a-EH_frame1 # FDE CIE offset
|
||||
.long LFB5a-. # FDE initial location
|
||||
.set L$set$33a,LFE5a-LFB5a
|
||||
.long L$set$33a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34a,LCFI21a-LFB5a
|
||||
.long L$set$34a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x40 # uleb128 0x40
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$35a,LCFI25a-LCFI21a
|
||||
.long L$set$35a
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE19a:
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
516
testsuite/unwind_test_x86_frameless_big.s
Normal file
516
testsuite/unwind_test_x86_frameless_big.s
Normal file
@ -0,0 +1,516 @@
|
||||
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_no_reg
|
||||
.long _test_ebx
|
||||
.long _test_esi
|
||||
.long _test_edi
|
||||
.long _test_ebx_esi
|
||||
.long _test_esi_edi
|
||||
.long _test_esi_edi_ebp
|
||||
.long _test_ebx_esi_edi
|
||||
.long _test_ebx_esi_ebp
|
||||
.long _test_ebx_esi_edi_ebp
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_ebx
|
||||
_test_ebx:
|
||||
LFB13:
|
||||
pushl %ebx
|
||||
LCFI0:
|
||||
subl $80024, %esp
|
||||
LCFI1:
|
||||
movl $0, %ebx
|
||||
call _uwind_to_main
|
||||
addl $80024, %esp
|
||||
popl %ebx
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_no_reg
|
||||
_test_no_reg:
|
||||
LFB12:
|
||||
subl $80028, %esp
|
||||
LCFI2:
|
||||
call _uwind_to_main
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE12:
|
||||
|
||||
|
||||
.globl _test_esi
|
||||
_test_esi:
|
||||
LFB10:
|
||||
pushl %esi
|
||||
LCFI5:
|
||||
subl $80024, %esp
|
||||
LCFI6:
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
addl $80024, %esp
|
||||
popl %esi
|
||||
ret
|
||||
LFE10:
|
||||
|
||||
|
||||
.globl _test_edi
|
||||
_test_edi:
|
||||
LFB11:
|
||||
pushl %edi
|
||||
LCFI3:
|
||||
subl $80024, %esp
|
||||
LCFI4:
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
addl $80024, %esp
|
||||
popl %edi
|
||||
ret
|
||||
LFE11:
|
||||
|
||||
|
||||
.globl _test_ebx_esi
|
||||
_test_ebx_esi:
|
||||
LFB9:
|
||||
nop
|
||||
subl $80028, %esp
|
||||
LCFI7:
|
||||
movl %ebx, 80020(%esp)
|
||||
LCFI8:
|
||||
movl %esi, 80024(%esp)
|
||||
LCFI9:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl 80020(%esp), %ebx
|
||||
movl 80024(%esp), %esi
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
.globl _test_esi_edi
|
||||
_test_esi_edi:
|
||||
LFB8:
|
||||
subl $80028, %esp
|
||||
LCFI10:
|
||||
movl %esi, 80020(%esp)
|
||||
LCFI11:
|
||||
movl %edi, 80024(%esp)
|
||||
LCFI12:
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl 80020(%esp), %esi
|
||||
movl 80024(%esp), %edi
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE8:
|
||||
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi
|
||||
_test_ebx_esi_edi:
|
||||
LFB7:
|
||||
subl $80028, %esp
|
||||
LCFI13:
|
||||
movl %ebx, 80016(%esp)
|
||||
LCFI14:
|
||||
movl %esi, 80020(%esp)
|
||||
LCFI15:
|
||||
movl %edi, 80024(%esp)
|
||||
LCFI16:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl 80016(%esp), %ebx
|
||||
movl 80020(%esp), %esi
|
||||
movl 80024(%esp), %edi
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_ebp
|
||||
_test_ebx_esi_ebp:
|
||||
LFB7a:
|
||||
subl $80028, %esp
|
||||
LCFI13a:
|
||||
movl %ebx, 80016(%esp)
|
||||
LCFI14a:
|
||||
movl %esi, 80020(%esp)
|
||||
LCFI15a:
|
||||
movl %ebp, 80024(%esp)
|
||||
LCFI16a:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %ebp
|
||||
call _uwind_to_main
|
||||
movl 80016(%esp), %ebx
|
||||
movl 80020(%esp), %esi
|
||||
movl 80024(%esp), %ebp
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE7a:
|
||||
|
||||
|
||||
|
||||
.globl _test_esi_edi_ebp
|
||||
_test_esi_edi_ebp:
|
||||
LFB6:
|
||||
subl $80028, %esp
|
||||
LCFI17:
|
||||
movl %esi, 80016(%esp)
|
||||
LCFI18:
|
||||
movl %edi, 80020(%esp)
|
||||
LCFI19:
|
||||
movl %ebp, 80024(%esp)
|
||||
LCFI20:
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
movl $0, %ebp
|
||||
call _uwind_to_main
|
||||
movl 80016(%esp), %esi
|
||||
movl 80020(%esp), %edi
|
||||
movl 80024(%esp), %ebp
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE6:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi_ebp
|
||||
_test_ebx_esi_edi_ebp:
|
||||
LFB5:
|
||||
subl $80028, %esp
|
||||
LCFI21:
|
||||
movl %ebx, 80012(%esp)
|
||||
LCFI22:
|
||||
movl %esi, 80016(%esp)
|
||||
LCFI23:
|
||||
movl %edi, 80020(%esp)
|
||||
LCFI24:
|
||||
movl %ebp, 80024(%esp)
|
||||
LCFI25:
|
||||
movl $0, %ebx
|
||||
movl $0, %esi
|
||||
movl $0, %edi
|
||||
movl $0, %ebp
|
||||
call _uwind_to_main
|
||||
movl 80012(%esp), %ebx
|
||||
movl 80016(%esp), %esi
|
||||
movl 80020(%esp), %edi
|
||||
movl 80024(%esp), %ebp
|
||||
addl $80028, %esp
|
||||
ret
|
||||
LFE5:
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
.globl _test_ebx.eh
|
||||
_test_ebx.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.long LFB13-. # FDE initial location
|
||||
.set L$set$2,LFE13-LFB13
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI0-LFB13
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI1-LCFI0
|
||||
.long L$set$4
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_no_reg.eh
|
||||
_test_no_reg.eh:
|
||||
LSFDE5:
|
||||
.set L$set$5,LEFDE5-LASFDE5
|
||||
.long L$set$5 # FDE Length
|
||||
LASFDE5:
|
||||
.long LASFDE5-EH_frame1 # FDE CIE offset
|
||||
.long LFB12-. # FDE initial location
|
||||
.set L$set$6,LFE12-LFB12
|
||||
.long L$set$6 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$7,LCFI2-LFB12
|
||||
.long L$set$7
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.align 2
|
||||
LEFDE5:
|
||||
|
||||
|
||||
.globl _test_esi.eh
|
||||
_test_esi.eh:
|
||||
LSFDE9:
|
||||
.set L$set$12,LEFDE9-LASFDE9
|
||||
.long L$set$12 # FDE Length
|
||||
LASFDE9:
|
||||
.long LASFDE9-EH_frame1 # FDE CIE offset
|
||||
.long LFB10-. # FDE initial location
|
||||
.set L$set$13,LFE10-LFB10
|
||||
.long L$set$13 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14,LCFI5-LFB10
|
||||
.long L$set$14
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15,LCFI6-LCFI5
|
||||
.long L$set$15
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE9:
|
||||
|
||||
|
||||
.globl _test_edi.eh
|
||||
_test_edi.eh:
|
||||
LSFDE10:
|
||||
.set L$set$12a,LEFDE10-LASFDE10
|
||||
.long L$set$12a # FDE Length
|
||||
LASFDE10:
|
||||
.long LASFDE10-EH_frame1 # FDE CIE offset
|
||||
.long LFB11-. # FDE initial location
|
||||
.set L$set$13a,LFE11-LFB11
|
||||
.long L$set$13a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$14a,LCFI3-LFB11
|
||||
.long L$set$14a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$15a,LCFI4-LCFI3
|
||||
.long L$set$15a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.align 2
|
||||
LEFDE10:
|
||||
|
||||
|
||||
|
||||
.globl _test_ebx_esi.eh
|
||||
_test_ebx_esi.eh:
|
||||
LSFDE11:
|
||||
.set L$set$16,LEFDE11-LASFDE11
|
||||
.long L$set$16 # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.long LFB9-. # FDE initial location
|
||||
.set L$set$17,LFE9-LFB9
|
||||
.long L$set$17 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$18,LCFI7-LFB9
|
||||
.long L$set$18
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$19,LCFI9-LCFI7
|
||||
.long L$set$19
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE11:
|
||||
|
||||
|
||||
.globl _test_esi_edi.eh
|
||||
_test_esi_edi.eh:
|
||||
LSFDE13:
|
||||
.set L$set$20,LEFDE13-LASFDE13
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE13:
|
||||
.long LASFDE13-EH_frame1 # FDE CIE offset
|
||||
.long LFB8-. # FDE initial location
|
||||
.set L$set$21,LFE8-LFB8
|
||||
.long L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI10-LFB8
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI12-LCFI10
|
||||
.long L$set$23
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.align 2
|
||||
LEFDE13:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi.eh
|
||||
_test_ebx_esi_edi.eh:
|
||||
LSFDE15:
|
||||
.set L$set$24,LEFDE15-LASFDE15
|
||||
.long L$set$24 # FDE Length
|
||||
LASFDE15:
|
||||
.long LASFDE15-EH_frame1 # FDE CIE offset
|
||||
.long LFB7-. # FDE initial location
|
||||
.set L$set$25,LFE7-LFB7
|
||||
.long L$set$25 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$26,LCFI13-LFB7
|
||||
.long L$set$26
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$27,LCFI16-LCFI13
|
||||
.long L$set$27
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE15:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_ebp.eh
|
||||
_test_ebx_esi_ebp.eh:
|
||||
LSFDE15a:
|
||||
.set L$set$24a,LEFDE15a-LASFDE15a
|
||||
.long L$set$24a # FDE Length
|
||||
LASFDE15a:
|
||||
.long LASFDE15a-EH_frame1 # FDE CIE offset
|
||||
.long LFB7a-. # FDE initial location
|
||||
.set L$set$25a,LFE7a-LFB7a
|
||||
.long L$set$25a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$26a,LCFI13a-LFB7a
|
||||
.long L$set$26a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$27a,LCFI16a-LCFI13a
|
||||
.long L$set$27a
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE15a:
|
||||
|
||||
|
||||
|
||||
.globl _test_esi_edi_ebp.eh
|
||||
_test_esi_edi_ebp.eh:
|
||||
LSFDE17:
|
||||
.set L$set$28,LEFDE17-LASFDE17
|
||||
.long L$set$28 # FDE Length
|
||||
LASFDE17:
|
||||
.long LASFDE17-EH_frame1 # FDE CIE offset
|
||||
.long LFB6-. # FDE initial location
|
||||
.set L$set$29,LFE6-LFB6
|
||||
.long L$set$29 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$30,LCFI17-LFB6
|
||||
.long L$set$30
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$31,LCFI20-LCFI17
|
||||
.long L$set$31
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE17:
|
||||
|
||||
|
||||
.globl _test_ebx_esi_edi_ebp.eh
|
||||
_test_ebx_esi_edi_ebp.eh:
|
||||
LSFDE19:
|
||||
.set L$set$32,LEFDE19-LASFDE19
|
||||
.long L$set$32 # FDE Length
|
||||
LASFDE19:
|
||||
.long LASFDE19-EH_frame1 # FDE CIE offset
|
||||
.long LFB5-. # FDE initial location
|
||||
.set L$set$33,LFE5-LFB5
|
||||
.long L$set$33 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI21-LFB5
|
||||
.long L$set$34
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0xa0,0xf1,0x4 # uleb128 0x138a0
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$35,LCFI25-LCFI21
|
||||
.long L$set$35
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE19:
|
||||
|
||||
|
||||
.subsections_via_symbols
|
330
testsuite/unwind_test_x86_unusual.s
Normal file
330
testsuite/unwind_test_x86_unusual.s
Normal file
@ -0,0 +1,330 @@
|
||||
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions
|
||||
# TEST-OPTIONS: unwind_test_main.c unwind_test_x86.s -arch i386 -fexceptions -Wl,-no_compact_unwind
|
||||
|
||||
|
||||
.data
|
||||
.globl _unwind_tester_list
|
||||
_unwind_tester_list:
|
||||
.long _test_ebx_wrong_slot
|
||||
.long _test_esi_in_ebx
|
||||
.long _test_edi_pad_ebx
|
||||
.long _test_coal_ebx_esi_edi
|
||||
.long Ltest_edi_pad_ebx
|
||||
.long 0
|
||||
|
||||
|
||||
.text
|
||||
|
||||
.globl _test_ebx_wrong_slot
|
||||
_test_ebx_wrong_slot:
|
||||
LFB13:
|
||||
pushl %ebp
|
||||
LCFI2:
|
||||
movl %esp, %ebp
|
||||
LCFI3:
|
||||
subl $4, %esp
|
||||
pushl %ebx
|
||||
LCFI4:
|
||||
subl $16, %esp
|
||||
LCFI5:
|
||||
movl $0, %ebx
|
||||
call _uwind_to_main
|
||||
addl $16, %esp
|
||||
popl %ebx
|
||||
addl $4, %esp
|
||||
leave
|
||||
ret
|
||||
LFE13:
|
||||
|
||||
|
||||
.globl _test_esi_in_ebx
|
||||
_test_esi_in_ebx:
|
||||
LFB9:
|
||||
pushl %ebp
|
||||
LCFI17:
|
||||
movl %esp, %ebp
|
||||
LCFI18:
|
||||
subl $24, %esp
|
||||
LCFI19:
|
||||
movl %ebx, -8(%ebp)
|
||||
LCFI20:
|
||||
movl %esi, %ebx
|
||||
LCFI21:
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl %ebx, %esi
|
||||
movl -8(%ebp), %ebx
|
||||
leave
|
||||
ret
|
||||
LFE9:
|
||||
|
||||
|
||||
|
||||
.globl _test_edi_pad_ebx
|
||||
_test_edi_pad_ebx:
|
||||
LFB7a:
|
||||
pushl %ebp
|
||||
LCFI27a:
|
||||
movl %esp, %ebp
|
||||
LCFI28a:
|
||||
subl $140, %esp
|
||||
LCFI29a:
|
||||
movl %edi, -44(%ebp)
|
||||
LCFI30a:
|
||||
LCFI31a:
|
||||
movl %ebx, -4(%ebp)
|
||||
LCFI32a:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -44(%ebp), %edi
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
||||
LFE7a:
|
||||
|
||||
Ltest_edi_pad_ebx:
|
||||
LFB7b:
|
||||
pushl %ebp
|
||||
LCFI27b:
|
||||
movl %esp, %ebp
|
||||
LCFI28b:
|
||||
subl $140, %esp
|
||||
LCFI29b:
|
||||
movl %edi, -44(%ebp)
|
||||
LCFI30b:
|
||||
LCFI31b:
|
||||
movl %ebx, -4(%ebp)
|
||||
LCFI32b:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
call _uwind_to_main
|
||||
movl -44(%ebp), %edi
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
||||
LFE7b:
|
||||
|
||||
|
||||
|
||||
.section __TEXT,__textcoal_nt,coalesced,pure_instructions
|
||||
.globl _test_coal_ebx_esi_edi
|
||||
.weak_definition _test_coal_ebx_esi_edi
|
||||
_test_coal_ebx_esi_edi:
|
||||
LFB7:
|
||||
pushl %ebp
|
||||
LCFI27:
|
||||
movl %esp, %ebp
|
||||
LCFI28:
|
||||
subl $40, %esp
|
||||
LCFI29:
|
||||
movl %ebx, -12(%ebp)
|
||||
LCFI30:
|
||||
movl %esi, -8(%ebp)
|
||||
LCFI31:
|
||||
movl %edi, -4(%ebp)
|
||||
LCFI32:
|
||||
movl $0, %ebx
|
||||
movl $0, %edi
|
||||
movl $0, %esi
|
||||
call _uwind_to_main
|
||||
movl -12(%ebp), %ebx
|
||||
movl -8(%ebp), %esi
|
||||
movl -4(%ebp), %edi
|
||||
leave
|
||||
ret
|
||||
LFE7:
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0 # Length of Common Information Entry
|
||||
LSCIE1:
|
||||
.long 0x0 # CIE Identifier Tag
|
||||
.byte 0x1 # CIE Version
|
||||
.ascii "zR\0" # CIE Augmentation
|
||||
.byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
|
||||
.byte 0x7c # sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x8 # CIE RA Column
|
||||
.byte 0x1 # uleb128 0x1; Augmentation size
|
||||
.byte 0x10 # FDE Encoding (pcrel)
|
||||
.byte 0xc # DW_CFA_def_cfa
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x88 # DW_CFA_offset, column 0x8
|
||||
.byte 0x1 # uleb128 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
|
||||
|
||||
|
||||
.globl _test_ebx_wrong_slot.eh
|
||||
_test_ebx_wrong_slot.eh:
|
||||
LSFDE3:
|
||||
.set L$set$1,LEFDE3-LASFDE3
|
||||
.long L$set$1 # FDE Length
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1 # FDE CIE offset
|
||||
.long LFB13-. # FDE initial location
|
||||
.set L$set$2,LFE13-LFB13
|
||||
.long L$set$2 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$3,LCFI2-LFB13
|
||||
.long L$set$3
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$4,LCFI3-LCFI2
|
||||
.long L$set$4
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$5,LCFI5-LCFI3
|
||||
.long L$set$5
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
|
||||
.globl _test_esi_in_ebx.eh
|
||||
_test_esi_in_ebx.eh:
|
||||
LSFDE11:
|
||||
.set L$set$20,LEFDE11-LASFDE11
|
||||
.long L$set$20 # FDE Length
|
||||
LASFDE11:
|
||||
.long LASFDE11-EH_frame1 # FDE CIE offset
|
||||
.long LFB9-. # FDE initial location
|
||||
.set L$set$21,LFE9-LFB9
|
||||
.long L$set$21 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$22,LCFI17-LFB9
|
||||
.long L$set$22
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$23,LCFI18-LCFI17
|
||||
.long L$set$23
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$24,LCFI21-LCFI18
|
||||
.long L$set$24
|
||||
.byte 0x09, 0x06, 0x03 # DW_CFA_register 6, 3
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.align 2
|
||||
LEFDE11:
|
||||
|
||||
|
||||
.globl _test_edi_pad_ebx.eh
|
||||
_test_edi_pad_ebx.eh:
|
||||
LSFDE15a:
|
||||
.set L$set$30,LEFDE15a-LASFDE15a
|
||||
.long L$set$30 # FDE Length
|
||||
LASFDE15a:
|
||||
.long LASFDE15a-EH_frame1 # FDE CIE offset
|
||||
.long LFB7a-. # FDE initial location
|
||||
.set L$set$31,LFE7a-LFB7a
|
||||
.long L$set$31 # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32,LCFI27a-LFB7a
|
||||
.long L$set$32
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33,LCFI28a-LCFI27a
|
||||
.long L$set$33
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34,LCFI32a-LCFI28a
|
||||
.long L$set$34
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0xD # uleb128 0xD
|
||||
.align 2
|
||||
LEFDE15a:
|
||||
|
||||
ltest_edi_pad_ebx.eh:
|
||||
LSFDE15b:
|
||||
.set L$set$30a,LEFDE15b-LASFDE15b
|
||||
.long L$set$30a # FDE Length
|
||||
LASFDE15b:
|
||||
.long LASFDE15b-EH_frame1 # FDE CIE offset
|
||||
.long LFB7b-. # FDE initial location
|
||||
.set L$set$31a,LFE7b-LFB7b
|
||||
.long L$set$31a # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32a,LCFI27b-LFB7b
|
||||
.long L$set$32a
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33a,LCFI28b-LCFI27b
|
||||
.long L$set$33a
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34a,LCFI32b-LCFI28b
|
||||
.long L$set$34a
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0xD # uleb128 0xD
|
||||
.align 2
|
||||
LEFDE15b:
|
||||
|
||||
.globl _test_coal_ebx_esi_edi.eh
|
||||
_test_coal_ebx_esi_edi.eh:
|
||||
LSFDE15:
|
||||
.set L$set$30b,LEFDE15-LASFDE15
|
||||
.long L$set$30b # FDE Length
|
||||
LASFDE15:
|
||||
.long LASFDE15-EH_frame1 # FDE CIE offset
|
||||
.long LFB7-. # FDE initial location
|
||||
.set L$set$31b,LFE7-LFB7
|
||||
.long L$set$31b # FDE address range
|
||||
.byte 0x0 # uleb128 0x0; Augmentation size
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$32b,LCFI27-LFB7
|
||||
.long L$set$32b
|
||||
.byte 0xe # DW_CFA_def_cfa_offset
|
||||
.byte 0x8 # uleb128 0x8
|
||||
.byte 0x84 # DW_CFA_offset, column 0x4
|
||||
.byte 0x2 # uleb128 0x2
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$33b,LCFI28-LCFI27
|
||||
.long L$set$33b
|
||||
.byte 0xd # DW_CFA_def_cfa_register
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x4 # DW_CFA_advance_loc4
|
||||
.set L$set$34b,LCFI32-LCFI28
|
||||
.long L$set$34b
|
||||
.byte 0x87 # DW_CFA_offset, column 0x7
|
||||
.byte 0x3 # uleb128 0x3
|
||||
.byte 0x86 # DW_CFA_offset, column 0x6
|
||||
.byte 0x4 # uleb128 0x4
|
||||
.byte 0x83 # DW_CFA_offset, column 0x3
|
||||
.byte 0x5 # uleb128 0x5
|
||||
.align 2
|
||||
LEFDE15:
|
||||
|
||||
|
||||
|
||||
.subsections_via_symbols
|
Loading…
Reference in New Issue
Block a user